Change NSImage brightness using NSSlider - objective-c

I am working on simple image processing app, here is my unsuccessful attempt to change NSImage brightness:
- (IBAction)brightnessSlider:(NSSlider*)sender {
ViewController *controller = (ViewController*)[NSApplication sharedApplication].keyWindow.contentViewController;
controller.imageView.image = originalImage;
CIImage* const beginImage = [self fromNSImageToCIImage:originalImage];
filter = [CIFilter filterWithName:#"CIColorControls" keysAndValues: kCIInputImageKey, beginImage, kCIInputBrightnessKey, [sender doubleValue], nil];
self->filteredImage = self->filter.outputImage;
controller.imageView.image = [self fromCIImageToNSImage:filteredImage];
}
Here is the implementation of fromNSImageToCIImage and fromCIImageToNSImage:
- (NSImage *)fromCIImageToNSImage:(CIImage *)inputImage {
struct CGImage *cg = [context createCGImage:inputImage fromRect:[inputImage extent]];
NSImage *finalImage = [[NSImage alloc] initWithCGImage:cg size:NSZeroSize];
return finalImage;
}
- (CIImage *)fromNSImageToCIImage:(NSImage *)inputImage {
struct CGImage *cg = [inputImage CGImageForProposedRect: nil context: nil hints: nil];
CIImage *temp = [[CIImage alloc] initWithCGImage: cg options: nil];
return temp;
}
Is it the right way to approach this? I don't even have a clue what is not working. Thanks.
EDITED (I rewrote the code and there's a problem with sender value):
- (IBAction)brightnessSlider:(NSSlider*)sender {
ViewController *controller = (ViewController*)[NSApplication sharedApplication].keyWindow.contentViewController;
CIImage* const beginImage = [self fromNSImageToCIImage:controller.imageView.image];
CIFilter *brightness = [CIFilter filterWithName:#"CIColorControls" keysAndValues: kCIInputImageKey, beginImage, #"inputBrightness", [sender doubleValue], nil];
CIImage *outputImage = brightness.outputImage;
struct CGImage* cgimg = [context createCGImage:outputImage fromRect:[outputImage extent]];
NSImage *newImage = [[NSImage alloc] initWithCGImage:cgimg size:NSZeroSize];
controller.imageView.image = newImage;
}
It crashes when NSSlider is used - in this line: CIFilter *brightness = [CIFilter filterWithName:#"CIColorControls" keysAndValues: kCIInputImageKey, beginImage, #"inputBrightness", [sender doubleValue], nil];
and debugger shows: Thread 1: EXC_BAD_ACCESS (code=1, address=0x6fbbba08)

Changing faulty line to this: CIFilter *brightness = [CIFilter filterWithName:#"CIColorControls" keysAndValues: kCIInputImageKey, beginImage, #"inputBrightness", [NSNumber numberWithFloat:[sender floatValue]], nil]; did the job.

Related

Adding CIFilters to selfie camera feed from ARSCNView

I'm setting up my ARScene using this code which works perfectly. I'm then trying to apply a CIFilter to the selfie camera feed and set it back in real time. The only way I can access the camera feed data is through the -session didUpdateFrame method (I think?) but when I apply the filter and set it back the feed is just pure white as if I set the background.contents = [UIColor White], which I did not.
self.sceneView = [[ARSCNView alloc] initWithFrame:self.view.frame];
self.sceneView.delegate = self;
self.sceneView.showsStatistics = NO;
[self.view addSubview:self.sceneView];
SCNScene *scene = [SCNScene new];
self.sceneView.scene = scene;
ARFaceTrackingConfiguration *facetrack = [[ARFaceTrackingConfiguration alloc] init];
[self.sceneView.session runWithConfiguration:facetrack];
self.sceneView.session.delegate = self;
- (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame {
CIImage *beginImage = [CIImage imageWithCVPixelBuffer: frame.capturedImage ];
CIFilter *filter = [CIFilter filterWithName:#"CIComicEffect" keysAndValues: kCIInputImageKey, beginImage, nil];
CIImage *outputImage = [[filter outputImage] imageByCroppingToRect:beginImage.extent];
UIImage *sat_img = [UIImage imageWithCIImage:outputImage];
self.sceneView.scene.background.contents = sat_img;
}
Is this even possible?

Blur CIImage as a CALayer Content image

I am using bellow code for image blur. 'resultImage' shows the blurred image, but when I put it on a CALayer content It shows nothing.
CIImage *imageToBlur = [CIImage imageWithCGImage:image.CGImage];
CIFilter *gaussianBlurFilter = [CIFilter filterWithName: #"CIGaussianBlur"];
[gaussianBlurFilter setValue:imageToBlur forKey: #"inputImage"];
[gaussianBlurFilter setValue:[NSNumber numberWithFloat: 10] forKey: #"inputRadius"];
CIImage *resultImage = [gaussianBlurFilter valueForKey: #"outputImage"];
self.contents = resultImage;
You cantn't use CIImage as a content of CALayer . There might be some VRM issue. I dont no more about it. By the way you may use CGImageRef instead of CIImage. Based on your code the thing you can do ...
CIImage *imageToBlur = [CIImage imageWithCGImage:image.CGImage];
CIFilter *gaussianBlurFilter = [CIFilter filterWithName: #"CIGaussianBlur"];
[gaussianBlurFilter setValue:imageToBlur forKey: #"inputImage"];
[gaussianBlurFilter setValue:[NSNumber numberWithFloat: 10] forKey: #"inputRadius"];
CIImage *resultImage = [gaussianBlurFilter valueForKey: #"outputImage"];
CIContext *cont = [CIContext contextWithOptions:nil];
CGImageRef img = [cont createCGImage:resultImage fromRect:CGRectMake(0, 0, image.size.width, image.size.height)];
self.contents = (__bridge id)img;
I hope it'll work!

Received memory warning objective c

I get Received memory warning 3 times and then the app crash.
I have a slider that need to change blur value into UIImageView image.
I try to work with dispatch_async and clean the image memory with imageView.image =nil; but the problem not solved.
this code call from uislider:
dispatch_async(dispatch_get_main_queue(), ^(void)
{
imageView.image =nil;
imageView.image = [self blurImage:originalImage withValue:value];
});
-(UIImage *)blurImage:(UIImage *)theImage withValue:(nullable id)value
{
CIFilter *gaussianBlurFilter = [CIFilter filterWithName:#"CIGaussianBlur"];
[gaussianBlurFilter setDefaults];
CIImage *inputImage = [CIImage imageWithCGImage:[theImage CGImage]];
[gaussianBlurFilter setValue:inputImage forKey:kCIInputImageKey];
[gaussianBlurFilter setValue:value forKey:kCIInputRadiusKey];
CIImage *outputImage = [gaussianBlurFilter outputImage];
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef cgimg = [context createCGImage:outputImage fromRect:[inputImage extent]];
UIImage *image = [UIImage imageWithCGImage:cgimg];
return image;
}
One of the assumption would be you did not release the CIImageRef cgimg. This might tend to add up memory.
-(UIImage *)blurImage:(UIImage *)theImage withValue:(nullable id)value
{
CIFilter *gaussianBlurFilter = [CIFilter filterWithName:#"CIGaussianBlur"];
[gaussianBlurFilter setDefaults];
CIImage *inputImage = [CIImage imageWithCGImage:[theImage CGImage]];
[gaussianBlurFilter setValue:inputImage forKey:kCIInputImageKey];
[gaussianBlurFilter setValue:value forKey:kCIInputRadiusKey];
CIImage *outputImage = [gaussianBlurFilter outputImage];
CIContext *context = [CIContext contextWithOptions:nil];
CGImageRef cgimg = [context createCGImage:outputImage fromRect:[inputImage extent]];
UIImage *image = [UIImage imageWithCGImage:cgimg];
//Release the core image reference
CGImageRelease(cgimg)
return image;
}

Geting an UIImage from an UIImageView

Currently I am working on a camera based app. I the camera image inside of a UIImageView to make it easier to manipulate. Now I want to add some effect from the core imaging. Can I somehow get a image out of the view.
This is how I add a effect but it works only for images.
NSString *filePath =
[[NSBundle mainBundle] pathForResource:#"IpadIcon" ofType:#"png"];
NSURL *fileNameAndPath = [NSURL fileURLWithPath:filePath];
CIImage *beginImage =
[CIImage imageWithContentsOfURL:fileNameAndPath];
CIContext *context = [CIContext contextWithOptions:nil];
CIFilter *filter = [CIFilter filterWithName:#"CISepiaTone" keysAndValues: kCIInputImageKey, beginImage, #"inputIntensity", [NSNumber numberWithFloat:0.8], nil];
CIImage *outputImage = [filter outputImage];
CGImageRef cgimg =
[context createCGImage:outputImage fromRect:[outputImage extent]];
UIImage *newImg = [UIImage imageWithCGImage:cgimg];
[captureImage setImage:newImg];
Getting the Image
- (void) capImage { //method to capture image from AVCaptureSession video feed
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in stillImageOutput.connections) {
for (AVCaptureInputPort *port in [connection inputPorts]) {
if ([[port mediaType] isEqual:AVMediaTypeVideo] ) {
videoConnection = connection;
break;
}
}
if (videoConnection) {
break;
}
}
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
if (imageSampleBuffer != NULL) {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
[self processImage:[UIImage imageWithData:imageData]];
}
}];
}
Get the image using UIImageView's image property:
UIImage *theImage = imageView.image;

Is it possible to change the header height of an NSTextView?

I am saving a PDF from an NSTextview and putting a logo in the header. I overrode pageHeader and the logo appears but it is clipped.
Is it possible to change the header height of an NSTextView?
Thanks!
Partial code:
-(IBAction)impLaudo:(id)sender
{
NSPrintInfo *printInfo;
NSPrintInfo *sharedInfo;
NSPrintOperation *printOp;
NSMutableDictionary *printInfoDict;
NSMutableDictionary *sharedDict;
sharedInfo = [NSPrintInfo sharedPrintInfo];
sharedDict = [sharedInfo dictionary];
printInfoDict = [NSMutableDictionary dictionaryWithDictionary:sharedDict];
[printInfoDict setObject:NSPrintSaveJob forKey:NSPrintJobDisposition];
[printInfoDict setObject:[[dirLaudos stringByAppendingString:[estudo stringValue]] stringByAppendingString:#".pdf"] forKey:NSPrintSavePath];
printInfo = [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
[printInfo setHorizontalPagination: NSClipPagination];
[printInfo setVerticalPagination: NSAutoPagination];
[printInfo setVerticallyCentered:NO];
[[printInfo dictionary] setValue:[NSNumber numberWithBool:YES] forKey:NSPrintHeaderAndFooter];
printOp = [NSPrintOperation printOperationWithView:textView printInfo:printInfo];
[printOp setShowsPrintPanel:NO];
[printOp runOperation];
}
#implementation MyTextView
- (NSAttributedString *)pageHeader
{
// Adicionando cabeƧalho
NSAttributedString *theHeader = nil;
NSImage * pic = [[NSImage alloc] initWithContentsOfFile:[dirLayout stringByAppendingString:#"cabecalho.jpg"]];
NSTextAttachmentCell *attachmentCell = [[NSTextAttachmentCell alloc] initImageCell:pic];
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
[attachment setAttachmentCell: attachmentCell ];
theHeader = [NSAttributedString attributedStringWithAttachment: attachment];
return theHeader;
}
#end
Instead of overriding -pageHeader, you should override -drawPageBorderWithSize:, which allows you to draw additional marks on the page at print time.
The Size parameter is an NSSize struct containing the size of the current logical page. All you need to do is draw your logo in the correct location:
- (void)drawPageBorderWithSize:(NSSize)pageSize
{
[super drawPageBorderWithSize:pageSize];
//draw your logo
NSPoint offset = NSMakePoint(100.0, 100.0);
NSImage* logo = [NSImage imageNamed:#"logo"];
NSSize logoSize = [logo size];
NSPoint imageOrigin = NSMakePoint(offset.x, pageSize.height - (offset.y + logoSize.height));
[self lockFocus];
[logo drawInRect:NSMakeRect(imageOrigin.x, imageOrigin.y, logoSize.width, logoSize.height)
fromRect:NSZeroRect
operation:NSCompositeSourceOver
fraction:1.0
respectFlipped:YES
hints:nil];
[self unlockFocus];
}