Change NSImage Origin - objective-c

Is it possible to change the origin of an NSImage? If so how would I go about doing this. I have coordinates in regular cartesian system some of them with negative values and I am trying to draw them at the corresponding point in the NSImage but since the origin is at (0,0) there are some missing.
EDIT:Say I have an drawing aspect that needs to be done to an image at the point (-10,-10), currently this doesn't show up. Is there a way to fix that?

If it's like in iOS (you may have to adapt a little the code) and if my memory is still good, you have to do this, since origin is readOnly:
CGRect myFrame = yourImage.frame;
myFrame.origin.x=newX; myFrame.origin.y=newY;
yourImage.frame = myFrame;

I think you are confusing an NSImage with it's container. An NSImage has no bounds or frame, and thus no origin. It does have a size which may represent the pixel dimensions of its birtmap representation ( if it has one) or otherwise could represent it's bounding box ( if it is a vector image). Drawing in an image at a pixel location of (-10,-10) doesn't really make sense.
An NSImage is displayed in a container ( typically an NSImageView), and the container's bounds.origin will dictate the placement of the image relative to the imageView, but you can't modify pixels beyond the edge of the bitmap plane.
In any case you probably want to be using a subclassed NSView in which you would override the drawRect method for your custom drawing. NSView does have a bounds.origin but this is not relevant to your in-drawing coordinates, but rather to the position of the drawn content as a whole to the view's bounding box. The coordinate system that you will be drawing into will be referenced to your graphics context which will (usually) pin the origin (0,0) to the bottom left corner (OSX) or top left corner (iOS). If you are trying to represent negative points on a Cartesian plane, you will need to apply a translation transform to map your points into this positive coordinate space.
I'm trying to explain in a few words, badly, something which Apple explains in great detail in their Quartz 2D Programming Guide.

Related

In iOS is it possible to change a View's coordinate system so that 0,0 is top right corner?

Normally the 0,0 coordinate refers to the top left corner of a view. Higher x coordinates are further right. A frame / rectangle in the view has its leftmost point being its x coordinate and its rightmost point being its x coordinate plus its width.
Is it possible to reverse that, or better yet, reverse just the x axis? Make the 0,0 be the top right. Make the higher origins be further to the left. AND make it so a frame / rectangle in the view has its rightmost point as its x coordinate and its leftmost point as its x coordinate plus its width.
I know I could transform this stuff myself with pure math, but I was wondering if iOS offers this capability.
Not really.
iOS 9 has some new flipping stuff for supporting right-to-left languages, but I don't think you can force it.
You can flip the drawing of a view by setting its transform property to CGAffineTransformMakeScale(-1, 1), but that won't change the underlying coordinate system.
SpriteKit has a different coordinate system than normal UIViews, but its coordinate system isn't what you want.
You may want to read Coordinate Systems and Transforms, which discusses some techniques for mapping points between different coordinate systems. This MSDN article covers mapping points using matrices, which can help you on a theoretical level.
It's not documented, but UIView has an instance variable, _flipsHorizontalAxis, that does exactly what it sounds like it would do. It looks like it just passes through the CALayer variable of the same name.

How to find back the real position on the image on iOS?

Here is the view I got, I got a layer view, detect user touch, and a image view, which showing the image. The layer view is cover on top of the image view. The image view's image is aspect fit. So, it won't lost the ratio. If in my layer view touch on 100, 240, it is a layer view coordinate, but not the image's coordinate. I would like to know how to convert the layer view's coordinate to a image's coordinate. In this example, the image size may be 180*180, so, the coordinate in layer view in the image is 60, 90.
Thanks.
If I'm understanding this question correctly, you want to take a point, which is currently in relation to the layer's coordinate system, and convert it to the image view's coordinate system?
In that case, there are a couple of ways to do this.
Easiest is to use convertPoint:fromView: or convertPoint:toView:
CGPoint imageViewTouchPoint = [layerView convertPoint:touchPoint fromView:imageView];
CGPoint imageViewTouchPoint = [imageView convertPoint:touchPoint toView:layerView];
Either one should work.
EDIT - I realize now that this is only if the UIImageView has the same frame as the UIImage, which you said it might not, due to the UIViewContentModeScaleAspectFit property.
In this case, unless I'm mistaken, the image frame is calculated inside the UIImageView drawRect: method and isn't a property that gets set. This means you'll have to calculate this on your own.
Definitely get the imageViewTouchPoint from one of the methods above (just in case you want to use the same logic on a UIImageView which isn't the full screen size).
You will then need to calculate the scaled image frame. There are a couple of ways to do this. Some people go brute force and manually calculate based on which side of the image is longer, then determining which side should be scaled. Then they calculate the origin by by centering the image and subtracting the image and image view's sides and dividing by two.
I like to write as little code as possible if it's unnecessary, even if it means importing a framework. If you import AVFoundation you get a method AVMakeRectWithAspectRatioInsideRect which you can use to actually calculate the scaled rectangle in one line of code.
CGRect imageRect = AVMakeRectWithAspectRatioInsideRect(image.size, imageView.frame);
Whichever method you use, you will then simply translate your touched point with the scaled image origin:
CGPoint imageTouchPoint = CGPointMake(imageViewTouchPoint.x - imageRect.origin.x, imageViewTouchPoint.y - imageRect.origin.y);
You have to do the math yourself. Calculate the aspect ratio of your image and compare with the aspect ratio of the image view's bounds.
Look at this question: How to Get Image position in ImageView
After searching more, got a hack:
CGSize imageInViewSize = [photo resizedImageWithContentMode:UIViewContentModeScaleAspectFit bounds:imageView.size interpolationQuality:kCGInterpolationNone].size;
CGRect overlayRect = CGRectMake((imageView.frame.size.width - imageInViewSize.width) / 2,
(imageView.frame.size.height - imageInViewSize.height) / 2,
imageInViewSize.width,
imageInViewSize.height);
NSLog(#"Frame of Image inside UIImageView: Left:%f Top:%f Width:%f Height:%f \n", overlayRect.origin.x, overlayRect.origin.y, overlayRect.size.width, overlayRect.size.height);

How to warp an UIImage using Open GL or any other method...?

I am trying to develop an iOS app to make any given image (UIImage) warp on selected locations.
So for this task to be accomplished what should be the rightmost way going forward, for now i'm doing some research on doing this on OpenGL (frankly any heads up on the framework would be nice too).
So finally the requirement is to get the UIImage warp on some given locations. (If x, y coordinates are there)
If you're sufficiently familiar with (or willing to learn) OpenGL, then you could do this:
Create a flat, rectangular grid of points to be a mesh that will be displayed with OpenGL.
Apply the image to the mesh as a texture.
When distorting the image at a particular location, you can just decide which points on the mesh will be affected by the distortion, and move them.
You can push points out from the center, or in toward a center, or shift them all in the same direction. If the distortion affects a large area, then you change a lot of points (possibly changing those in the center by more than those near the edges of the affected area).
Not sure what you mean by 'warp'. Do you mean skew it in 3 dimensions? If so you can adjust the CGAffineTransform for the UIImageView you are displaying it in to get that effect.
If you mean some kind of image processing warp, and you are using iOS 5, you can use Core Image for that.

regarding rotating the map in iOS

I am facing this problem while trying to rotate the map in my iPhone app
The view gets clipped and rotation also happens. I want to avoid the clipping. Any tips ?
heres the code:
viewToRotate.layer.transform = CATransform3DMakeRotation(0.8, 0., 0., 1.);
You need your map rotated in 3D ? If not (which is what I think you need), then just use CGAffineTransformMakeRotation (be careful, as it requires the angle in radians).
Also, if you don't want your map to be clipped, you need to make your map bigger, like in the image below (open in new tab to see it bigger)
http://img593.imageshack.us/img593/4498/calculatemapboundswhenr.png
First, you need to calculate the diagonal of the rectangle (your visible map) as instructed in the image above (which I call "radius" because that would be the radius of the smallest circle bigger than your rectangle).
Second, using the radius, you need to calculate the (smallest) square that will allow your map to be seen without clipping. This square will be used to set the bounds of your map (caution: NOT the frame - Apple specifies that, when using rotation, you should not use frame - just bounds and / or center).
Make sure this square is centered on the center of your visible map rectangle (i.e. the square should have X pixels above AND below the small rectangle ... and Y pixels left AND right of the small rectangle).
Hope it helps !
Did you ever figure out the solution?
The only way I could do it was to make the MapView in Interface Builder much bigger than the actual size of the screen area its supposed to cover, then I centered the MapView such that its center was in the center of the narrower viewable area.
Rotation seemed to work similarly to how it works in the built-in Maps app.
My guess is that you have to do this so that the image tiles streaming in from Google cover a wide enough area to "fill in the blanks" so to speak, even if they're not always visable.
If you apply a little math, you could probably programmatically size and position the MapView such that you void clipping, but don't require more tiles than is absolutely necessary.

How to recognize the touch of a non regular sprite image?

I have a sprite and if it is touched the touch should be recognized. I used the coordinates to do so. I took the coordinates (min x, min y, max x , max y)of the sprite image. But The sprite image is not a rectangular shape. So, even if I touch the coordinates outside the sprite and inside the rectangular bounds the sprite is recognized.
But for my application I need only the sprite to be recognized. So, I have to take only the coordinates of the sprite, but it is not regular shape. I am using CCSprite in my program.
So, what can I do to for only the sprite to be selected ? Which classes should use for this?
Thank You.
You could try one of the following...
Create a bounding box smaller than the absolute extents of the sprite image. Yes it will be smaller than the sprite. This will eliminate the dead space click detection of the sprite the trade off being parts of your sprite which look selectable won't be
Use a circular bounding area to detect if the user has clicked on your sprite. Again you will have the dead space problem in my first suggestion but the sphere may give you some better coverage area over the sprite giving you better results on touch detection
This is a standard problem in physics collision detection systems which often end up using circles or rectangles as their collision bodies. I would go with the either a circle or rectangle smaller than the size of your sprite as your bounding area. Going finer detail than that you could generate bounding area polygons. This would however introduce a whole bunch of new issues and concerns.
I am building a Cocos2D game right now and what I am doing is first I step through my sprites and see which sprites the touch hit (they overlap in my app)
Then, for each sprite hit I use [sprite convertTouchToNodeSpace] to get an X,Y co-ordinate inside the sprite, which I can use (although the Y axis is flipped) to reference the CGImage I created the sprite with.
If the pixel at the touch point is 'clear' ie alpha 0, then the sprite was not really touched, and I check the next sprite in the z-order to see if it has color where it was touched.
Sometimes I think I should be using a two color mask image to go along with each sprite, not the sprite image. But, I am mr. make it work, then make it fast.
I realise this is not super efficient, but I do not have very many sprites and I do this only for touches.