Using drawAtPoint with my CIImage not doing anything on screen - objective-c

Stuck again. :(
I have the following code crammed into a procedure invoked when I click on a button on my application main window. I'm just trying to tweak a CIIMage and then display the results. At this point I'm not even worried about exactly where / how to display it. I'm just trying to slam it up on the window to make sure my Transform worked. This code seems to work down through the drawAtPoint message. But I never see anything on the screen. What's wrong? Thanks.
Also, as far as displaying it in a particular location on the window ... is the best technique to put a frame of some sort on the window, then get the coordinates of that frame and "draw into" that rectangle? Or use a specific control from IB? Or what? Thanks again.
// earlier I initialize a NSImage from JPG file on disk.
// then create NSBitmapImageRep from the NSImage. This all works fine.
// then ...
CIImage * inputCIimage = [[CIImage alloc] initWithBitmapImageRep:inputBitmap];
if (inputCIimage == Nil)
NSLog(#"could not create CI Image");
else {
NSLog (#"CI Image created. working on transform");
CIFilter *transform = [CIFilter filterWithName:#"CIAffineTransform"];
[transform setDefaults];
[transform setValue:inputCIimage forKey:#"inputImage"];
NSAffineTransform *affineTransform = [NSAffineTransform transform];
[affineTransform rotateByDegrees:3];
[transform setValue:affineTransform forKey:#"inputTransform"];
CIImage * myResult = [transform valueForKey:#"outputImage"];
if (myResult == Nil)
NSLog(#"Transformation failed");
else {
NSLog(#"Created transformation successfully ... now render it");
[myResult drawAtPoint: NSMakePoint ( 0,0 )
fromRect: NSMakeRect ( 0,0,128,128 )
operation: NSCompositeSourceOver
fraction: 1.0]; //100% opaque
[inputCIimage release];
}
}
Edit #1:
snip - removed the prior code sample mentioned below (in the comments about drawRect), which did not work
Edit #2: adding some code that DOES work, for anyone else in the future who might be stuck on this same thing. Not sure if this is the BEST way to do it ... but it does work for my quick and dirty purposes. So this new code (below) replaces the entire [myResult drawAtPoint ...] message from above / in my initial question. This code takes the image created by the CIImage transform and displays it in the NSImageView control.
NSImage *outputImage;
NSCIImageRep *ir;
ir = [NSCIImageRep imageRepWithCIImage:myResult];
outputImage = [[[NSImage alloc] initWithSize: NSMakeSize(inputImage.size.width, inputImage.size.height)] autorelease];
[outputImage addRepresentation:ir];
[outputImageView setImage: outputImage]; //outputImageView is an NSImageView control on my application's main window

Drawing on screen in Cocoa normally takes place inside an -[NSView drawRect:] override. I take it you're not doing that, so you don't have a correctly set up graphics context.

So one solution to this problem is to create a NSCIImageRep from the CIImage, then add that representation to a new NSImage, then it is easy to display the NSImage in a variety of ways. I've added the code I used up above (see "edit #2"), where I display the "output image" within an NSImageView control. Man ... what a PITA this was!

Related

Objective C - UIImage resizing not working

I have a program that fetches an image from the library, but I'm using code I found online to resize that image so that it can fit on the screen (basically making it 640x960), but then it would still be too big to display, so in another UIImage I'm copying the first resized image and re-resizing this one to make it about 1/4 of the screen (or 160x240). The code is this:
for ViewController.h:
UIImage *img;
UIImage *thumb;
-(UIImage*) scaleImage: (UIImage*)image toSize:(CGSize)newSize;
(this of course, is only the code related to my problem)
for ViewController.m
-(UIImage*) scaleImage: (UIImage*)image toSize:(CGSize)newSize {
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
and in the same m file on another function, the scaleImage function is called when pressing a button with these lines:
[self scaleImage:img toSize:CGSizeMake(640, 960)];
thumb = img;
[self scaleImage:thumb toSize:CGSizeMake(160, 240)];
In the project I've previously been able to successfully provide an image for img using [info objectForKey:UIImagePickerControllerOriginalImage]; which would be the image chosen from the library. I've already "file owned" everything so that this function takes place (and it does because I create an UIAlert within it and it shows, and a NSLog to print out when scaleImage starts and it does, twice), but the image is never re-sized!! Does anyone know why?? Please let me know, thank you for anyone who comments with help or suggestions!!
Your scaleImage method returns the scaled image, for example
thumb = [self scaleImage:img toSize:CGSizeMake(640, 960)];

To Convert HTML doc to image in cocoa

is it possible to convert the HTML page to image in cocoa?
Actually i have created the complete view in the HTML and now i want to convert the whole html preview to the image (any jpeg or png etc.).
I couldn't find any resource or sample on the web, which provides some sort of help on my above queries.It's highly appreciated if someone could share his wisdom on how I can achieve this.
Thanks in advance..
First off, I'd like to thank sergio... his answer got me started but I thought I'd share some of the code that I didn't find obvious that I had to write to make it work:
Here's how to make a thumbnail for a page without ever having it displayed:
// Your width and height can be whatever you like, but if you want this to render
// off screen, you need an x and y bigger than the superview's width and height
UIWebView* webView = [[UIWebView alloc] initWithFrame:CGRectMake(largerScreenDimension, largerScreenDimension, largerScreenDimension, largerScreenDimension)];
[self.view addSubview:webView]; // UIWebViews without an assigned superview don't load ever.
webView.delegate = self; // or whoever you have implement UIWebViewDelegate
webView.scalesToFit = YES; // This zooms the page appropriately to fill the entire thumbnail.
[webView loadRequest:[NSURLRequest requestWithURL:url]];
Then implement this in your delegate:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
UIGraphicsBeginImageContext(webView.bounds.size);
[webView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *webViewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *thumbnailData = UIImagePNGRepresentation(webViewImage);
[webView removeFromSuperview];
}
Finally, to display this thumbnail you'll need something like:
thumbnailImageView.image = [UIImage imageWithData:thumbnailData];
As a bonus thing I'll mention, I wanted multiple thumbnails to be generated at once. I found using objc_setAssociatedObject() and objc_getAssociatedObject() to be very helpful with keeping track of which webView was loading which thumbnail. Going into detail on how that worked is beyond the scope of this question, though.
You can draw your view in an image context, like this:
UIWebView* view = ...
....
UIGraphicsBeginImageContext(view.bounds.size);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imagedata = UIImagePNGRepresentation(viewimage);
NSString *encodedString = [imageData base64Encoding];
Another option would be using Quartz PDF engine to create a PDF.

Mirroring CIImage/NSImage

Currently I have the following
CIImage *img = [CIImage imageWithCVImageBuffer: imageBuffer];
NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:img];
NSImage *image = [[[NSImage alloc] initWithSize: [imageRep size]] autorelease];
[image addRepresentation:imageRep];
This works perfectly, I can use the NSImage and when written to a file the image is exactly how I need it to be.
However, I'm pulling this image from the users iSight using QTKit, so I need to be able to flip this image across the y axis.
My first thought was to transform the CIImage using something like this, however my final image always comes out completely blank. When written to a file the dimensions are correct but it's seemingly empty.
- (CIImage *)flipImage:(CIImage *)image
{
return [image imageByApplyingTransform:CGAffineTransformMakeScale(-1, 1)];
}
Am I approaching this the wrong way? Or have I made a mistake in my code?
That transform flips it, but the axis around which it flips is not at the center of the image, but at the left edge. You must also translate the image by its width to account for the movement caused during the scale.
Here is some code that may help someone out ==>
CGAffineTransform rotTrans = CGAffineTransformMakeRotation(M_PI_2);
CGAffineTransform transTrans1 = CGAffineTransformTranslate(rotTrans, 0.0f, 320.0f);
CGAffineTransform scaleTrans = CGAffineTransformScale(transTrans1, 1.0, -1.0);
CGAffineTransform transTrans2 = CGAffineTransformTranslate(scaleTrans, -0.0f, -320.0f);
self.view.transform = transTrans2;
I use it to flip frames from the front camera horizontally so they always appear up no matter what the rotation of the device. This stuff does get kind of tricky. One thing to do to help figure out what is going on is scaling down along either of the axes and seeing what the result is.

Can't draw UImage in UIView::drawRect

I know this seems like a simple task, which is why I don't understand why I can't get the image to render.
When I set up my UIView, I do the following:
myUiView.backgroundColor = [UIColor clearColor];
myUiView.opaque = NO;
I create and retain the UIImage in the init function of my UIView:
image = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"test" ofType:#"png"]] retain];
then my drawRect looks like this:
- (void) drawRect:(CGRect) rect
{
[image drawInRect:self.bounds];
}
Ultimately I'll be manipulating that UIImage via bitmap context, and then in drawRect create a CGImage out of the context, and render that, but for now I'm just trying to get it rendering a known image.
I've been digging through this site, as well as the documentation. I've gone down the CG path and tried drawing it with CGContextDrawImage by following the numerous examples other people have posted, but that didn't work either.
So I've come back to what seems to be the most straightforward way to draw an image, but it isn't working.
Any help would be greatly appreciated.
Thanks in advance.
First of all, verify that the size and position of self.bounds are what you want them to be. If the size is {0,0} nothing will display. Check using this function:
NSLog(#"%#", NSStringFromCGRect(self.bounds));
Also make sure that the image is not nil:
NSLog(#"%#", image);

Another IKImageView Question: copying a region

I'm trying to use the select and copy feature of the IKImageView. If all you want to do is have an app with an image, select a portion and copy it to the clipboard, it's easy. You set the copy menu pick to the first responder's copy:(id) method and magically everything works.
However, if you want something more complicated, like you want to copy as part of some other operation, I can't seem to find the method to do this.
IKImageView doesn't seem to have a copy method, it doesn't seem to have a method that will even tell you the selected rectangle!
I have gone through Hillegass' book, so I understand how the clipboard works, just not how to get the portion of the image out of the view...
Now, I'm starting to think that I made a mistake in basing my project on IKImageView, but it's what Preview is built on (or so I've read), so I figured it had to be stable... and anyway, now it's too late, I'm too deep in this to start over...
So, other than not using IKImageView, any suggestions on how to copy the select region to the clipboard manually?
EDIT actually, I have found the copy(id) method, but when I call it, I get
<Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 16 bits/pixel; 1-component color space; kCGImageAlphaPremultipliedLast; 2624 bytes/row.
Which obviously doesn't happen when I do a normal copy through the first-responder... I understand the error message, but I'm not sure where it's getting those parameters from...
Is there any way to trace through this and see how this is happening? A debugger won't help for obvious reasons, as well as the fact that I'm doing this in Mozilla, so a debugger isn't an option anyway...
EDIT 2 It occurs to me that the copy:(id) method I found may be copying the VIEW rather than copying a chunk of the image to the clipboard, which is what I need.
The reason I thought it was the clipboard copy is that in another project, where I'm copying from an IKImageView to the clipboard straight from the edit menu, it just sends a copy:(id) to the firstResponder, but I'm not actually sure what the firstresponder does with it...
EDIT 3 It appears that the CGBitmapContextCreate error is coming from [imageView image] which, oddly enough, IS a documented method.
It's possible that this is happening because I'm putting the image in there with a setImage:(id) method, passing it an NSImage*... Is there some other, more clever way of getting an NSImage into an IKImageView?
The -copy: method in IKImageView does what every other -copy: method does: it copies the current selection to the clipboard. It is, however, implemented as a private method in IKImageView for some reason.
You can just call it directly:
[imageView copy:nil];
This will copy whatever is currently selected to the clipboard.
I don't think there's a way to directly access the image content of the current selection in IKImageView using public methods, this is a good candidate for a bug report/feature request.
You can, however, use the private method -selectionRect to get a CGRect of the current selection and use that to extract the selected portion of the image:
//stop the compiler from complaining when we call a private method
#interface IKImageView (CompilerSTFU)
- (CGRect)selectionRect
#end
#implementation YourController
//imageView is an IBOutlet connected to your IKImageView
- (NSImage*)selectedImage
{
//get the current selection
CGRect selection = [imageView selectionRect];
//get the portion of the image that the selection defines
CGImageRef selectedImage = CGImageCreateWithImageInRect([imageView image],(CGRect)selection);
//convert it to an NSBitmapImageRep
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithCGImage:selectedImage] autorelease];
CGImageRelease(selectedImage);
//create an image from the bitmap data
NSImage* image = [[[NSImage alloc] initWithData:[bitmap TIFFRepresentation]] autorelease];
//in 10.6 you can skip converting to an NSBitmapImageRep by doing this:
//NSImage* image = [[NSImage alloc] initWithCGImage:selectedImage size:NSZeroSize];
return image;
}
#end
Ok, so the copy: nil fails, and the [imageView image] fails, but it turns out that I have another copy of the NSImage from when I added it into the view in the first place, so I could that. Also, CGImageCreateWithImageInRect expects a CGImageRef not an NSImage*, so I had to do some conversions.
In addition, for some reason the selection rectangle is flipped, either it's bottom origined, and the image is top, or the other way around, so I had to flip it.
And for some reason, the compiler suddenly started complaining that NSRect isn't the same type as CGRect (Which implies that it suddenly went from 32 to 64 bit or something... not sure why...)
Anyway, here is my copy of selectedImage:
- (NSImage*)selectedImage
{
//get the current selection
CGRect selection = flipCGRect(imageView, [imageView selectionRect]);
//get the portion of the image that the selection defines
struct CGImage * full = [[doc currentImage] CGImageForProposedRect: NULL context: NULL hints: NULL];
CGImageRef selectedImage = CGImageCreateWithImageInRect( full, selection);
//convert it to an NSBitmapImageRep
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc] initWithCGImage:selectedImage] autorelease];
CGImageRelease(selectedImage);
// //create an image from the bitmap data
NSImage* image = [[[NSImage alloc] initWithData:[bitmap TIFFRepresentation]] autorelease];
// //in 10.6 you can skip converting to an NSBitmapImageRep by doing this:
//NSImage* image = [[NSImage alloc] initWithCGImage:selectedImage size:NSZeroSize];
return image;
}
I wrote flipCGRect, and [doc currentImage] returns an NSImage*...