how to translate and scale a NSImage? - cocoa

I have built so far an application that allows the user to drag and drop images onto a NSImageView. However, I want to be able to move these images by simply clicking on any image and hold down the mouse button to move it's location.
How can I manipulate NSImageView to translate/scale after setting the images down? Is that possible? I've read about the NSAffineTransform, but it seems like that is moving the images before creating the image itself. I already have the images on the canvas, and simply want to click and hold the image and move it with my mouse. Please help anyone!

There are two sides to this.
NSImage is the model object, which you might want to display in different ways, save to disk/archive, etc. If you want to actually change the model (scaling, rotating, etc.), implying a permanent change, then you are going to probably want to look at NSAffineTransform, Quartz drawing, etc.
But you probably didn't mean that. Instead you probably are interested in NSImageView, which is a view object, displaying the contents of the NSImage model object using whatever display attributes are desired. If you only want to change how an image is displayed, not what the actual bytes in the image are, then you are going to manipulate the NSImageView at run-time. You can use NSAffineTransform here as well, but it's somewhat uncommon (and usually unnecessary).
The key thing to note that is the NSImageView inherits from NSView, so you have all its power at your disposal. Take a look at certain methods, such as:
-setFrameSize: - useful for changing the view size, and thus the image display scale
-setFrameOrigin: - useful for changing the view position, and thus the apparent image position
Note again that these have nothing to do with images per se, and apply to all Cocoa views. You may want to take a look at a book like Cocoa Programming for Mac OS X to get you past the basics. (You can then do more interesting things, like rotation, animation, etc.)

Related

Xcode GLKit printing Text on GLKView without using UIImages

I have an app, its a small game using opengles with GLKit.
No im wondering how it works when i want to draw text on
my screen (if it is possible).
How can i do it?
i draw all of my game objects using images (wrapped in some kind
of sprite). its possible to scale, to move, and to rotate.
everything works fine.
but finding out how it works to print text on that glkview
gets me deep inside of problems ^^
I dont want to use uiimages cause i also dont know how
to present uiimages on a glkview.
There are a number of ways to do what you want:
1) Have an image with all the text glyphs you need in it. For example, if your application is in English, you'd have the 26 uppercase and 26 lowercase letters in the image. Upload that texture to the GPU and use the proper texture coordinates or glSubTexImage2d() to pull out the glyphs you need. (It's not clear to me if this is what you meant by not wanting a UIImage. It doesn't have to be a UIImage, though that's probably easiest.)
2) Every time you need to display text, draw it on the CPU on the fly, and upload the entire word, phrase, or sentence as a texture. You could create a CGBitmapContext and use Core Graphics to draw text to it. Then upload it using glTexImage2D().
3) Get the individual glyphs out of the fonts and draw directly using the bezier curves that make up the glyphs. This allows for 3D extrusion, too. However, this option is the most time consuming to code and probably least performant. It also involves dealing with the many small problems that fonts have (like degenerate segments, and incorrect winding orders). IF you want to go down this path, I think maybe Core Text can help.
There are at least two clean ways to do this, depending on your requirements.
While documentation advises against compositing over a CAEAGLLayer (GLKView), it works quite well, at least in recent iOS versions, when transparent content is layered on top of the CAEAGLLayer. For example, try dropping a UITextView, with opaque set to false and a clear background color, on top of a GLKView in your Storyboard in Interface Builder in the Apple GLKit template or your app. In my test on an iPhone 5, frame rendering time remained around 1ms, even while scrolling in the text view. If your text needs are static, or you don't want the user to interact with the text, use CATextLayer as a child layer of your EAGLLayer instead of a view.
The second approach is to render the text into a texture. You can then composite the text onto your view by disabling the depth buffer and rendering the texture on a full screen rectangle. Look at UIGraphicsBeginImageContextWithOptions to see how to render to an offscreen image with Quartz. UIGraphicsGetImageFromCurrentImageContext allows you to retrieve the UIImage to use as a texture.

Creating images from views, strings, etc

Ok so I have a problem. I have a method that is called imageFromText, it requires one parameter, the string itself, and it returns a NSImage. I also have another one which is called: imageFromView, this one basically have to "take a screenshot" of the view and return a NSImage, it also has only one parameter, the view itself. So it looks like this:
-(NSImage*)imageFromText: (NSString*)text {
}
-(NSImage*)imageFromView: (NSView*)view {
}
There's only one problem, I have no idea how to do this. Well so, I spent my afternoon searching around and I didn't find nothing. I've tried, to the second one, a method dataWithPDFInsideRect, but obviously, this method was not made to this propose. Please help me out!.
PLEASE NOT: I'M NOT ASKING FOR THE CODE READY. LIKE THE OLD DICTATION (IN MY COUNTY): DON'T GIVE THEM THE FISH, THEACH THEM HOW TO FISH. (TRANSLATED).
An alternative way is to lock focus on the view, then create a bitmap image rep with the contents of the view's bounds. You can then create a blank image whose size is the size of the bounds, and add the image rep to it.
The third way is dataWithPDFInsideRect:. Yes, the one you tried and couldn't get to work (I wish you'd explained what problem you had with it instead of just dismissing it!). Pass the view's bounds, then pass the data to NSImage's initWithData:.
As for imageFromView: check the Organizer Documentation for Screen Capture.
And imageFromText: You want an image (PNG I assume) that just shows a text? Don't you want to specify things like image size, font size, font color, background color, ...?
Summarizing, lock focus on the image, then draw. The NSImage docs should have more if you search for lockFocus.
The methods you're interested in are:
-[NSImage lockFocus]
+[NSGraphicsContext currentContext]
-[NSView displayRectIgnoringOpacity:inContext:]
-[NSImage lockFocus]
To draw to an image, allocate one, and then lock focus on it, then issue drawing calls and then unlock focus.
To draw a view into an image, lock focus on an image, get the current graphic context (which is now the image), and pass that to -[NSView displayRectIgnoringOpacity:inContext:].

Touch to move through images

I have an NSMutableArray of jpg images and I want to be able to touch and, moving my finger from right to left, move through the array of images in order. I've been reading about UIScrollView, but I'm not sure if this accomplishes what I am looking for. It seems to me that UIScrollView is more used for viewing an object that is too large to be displayed entirely on the screen and you need to be able to move to see every part of the object. I need to move to an entirely new image, the next image in my array. What is the best way to go about this?
You certainly can use a UIScrollView for what you want. A scroll view can be used, as you noted, to scroll an area that is too large for the screen. However, you can also use it to scroll through "pages". This is really the best way to do what you want, short of rolling your won scroll view.
There is a property of UIScrollView, called pagingEnabled, which you'll want to set to YES. I suggest that you give it a try. Also, have a look at the UIScrollView documentation and the Scroll View programming guide. It will tell you all that you need to know about UIScrollViews. Also, remember that for proper memory management, you'll want to only load three images at any given time. See this answer that I wrote for more information on that, and on UIScrollViews in general.

Cocoa: Custom control not limited to window frame - how to start?

I want to build a custom control that would work like this:
You have a kind of NSButton with an image.
You click the button and than appears a big square with a grid of photos.
You click one of the photos and it is set up as new image for the button. (square dissapears)
Now, how to draw this big square with photos if I want it not to be limited to window frame?
I mean, if the button was close to window border the square is going to be partially outside window. I would also like to add some shadow to the square and an animation for opening/closing.
One important thing: I want to be able to draw not only a square but any other simple shape (circle)!
This isn't really a drawing question so much as a general custom views question. It's important to make that distinction.
I'll describe this in terms of rectangles to give you the general idea*. You should make sure you understand the view hierarchy and view geometry in Cocoa. Without this important requisite knowledge, you'll remain dead in the water.
It's easy to set an NSButton's image, so I'll leave that to you. Your button's action, however, would tell some controller to show the "image picker" for the given button. Your image picker would be some type of borderless window with an image list inside. The image picker could be an IKImageBrowserView (you'll have to enable Image Kit in Interface Builder for this control to appear), which gives you an iPhoto-like grid of images (with/without titles, different border types, etc.).
An explanation of the operation of this controller and how it creates the window, manages the selection, and sets the button's image is very broad so if you get hung up on any of those steps, you'll need to create a separate question for each problem, otherwise this answer would have to be an instruction manual for writing your app for you.
* Your problem is a little more difficult because of your desire to have differently-shaped "popup windows" ... you'd have to make sure your available photos fit neatly within the shape so none of them are cut off. Armed with the basic knowledge of view geometry, I'll leave this to you as an exercise. A hint: you can use a borderless, transparent window to host a view that draws itself in any shape you please.

How does CATransition work?

CATransition is quite unusual. Consider the following code.
CATransition* trans=[CATransition animation];
trans.duration=0.5;
trans.type=kCATransitionFade;
[self.holdingView.layer addAnimation:trans forKey:nil];
self.loadingView.hidden=YES;
self.displayView.hidden=NO;
Notice that nowhere did I tell the transition that I wanted to display the displayView rather than loadingView, so the views must somehow access the transition themselves. Can anyone explain in more detail how this works?
When you add the transition as an animation, an implicit CATransaction is begun. From that point on, all modifications to layer properties are going to be animated rather than immediately applied. The way the CATransition performs this animation to to take a snapshot of the view before the layer properties are changed, and a snapshot of what the view will look like after the layer properties are changed. It then uses a filter (on Mac this is Core Image, but on iPhone I'm guessing it's just hard-coded math) to iterate between those two images over time.
This is a key feature of Core Animation. Your draw logic doesn't generally need to deal with the animation. You're given a graphics context, you draw into it, you're done. The system handles compositing that with other images over time (or rotating it in space, or whatever). So in the case of changing the hidden state, the initial-state fully composited image is blended with the final-state composted image. Very fast on a GPU, and it doesn't really matter what change you made to the view.

Resources