Down-scaling an UIImage - objective-c

I am having problems with resizing of my JPEG picture.
I would like it to be the size of the original picture, but instead it covers up the whole screen. I was trying myImageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"Cube Tile.jpeg"]
myImageView.contentMode = UIViewContentModeScaleAspectFit;
This is what happened:
My simulator screen gets covered with my image, but the height is slightly smaller.
I also tried adding this: myImageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"Cube Tile.jpeg"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]];
This is what happened:
My simulator screen gets covered with tiny versions of my image.
Is it possible doing this without too many lines of code?
Excuse me if I am a bit vaque.
Note 1: The original picture is 24 x 24 pixels
Note 2: I am a new developer, so I was just experimenting.
Thanks in advance, Marnix.

Have you tried setting the frame on the image view? e.g.,
float x = 0.0;
float y = 0.0;
[myImageView setFrame:CGRectMake(x,y,24,24)];
(and to make sure it's not trying to autosize based on a setting in the .xib)
[myImageView setAutoresizingMask:UIViewAutoresizingNone];

You could change the value of
myImageView.contentMode = UIViewContentModeScaleAspectFit;
to one of these Values:
typedef enum {
UIViewContentModeScaleToFill,
UIViewContentModeScaleAspectFit,
UIViewContentModeScaleAspectFill,
UIViewContentModeRedraw,
UIViewContentModeCenter,
UIViewContentModeTop,
UIViewContentModeBottom,
UIViewContentModeLeft,
UIViewContentModeRight,
UIViewContentModeTopLeft,
UIViewContentModeTopRight,
UIViewContentModeBottomLeft,
UIViewContentModeBottomRight,
} UIViewContentMode;
See more at the official documentation http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/uiview/uiview.html

Related

How to properly position the back button in iOS7

I used this code to use a custom image as the back button in the whole app.
[[UINavigationBar appearance] setBackIndicatorImage:[UIImage imageNamed:#"back"]];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:[UIImage imageNamed:#"back"]];
The image dimensions are 30 x 30.
The code adds the image as the back button but the position is not the correct, as you can see in the following image:
Any ideas on how to properly position the image without modifying its dimensions (at least the visual part of the image (circle + arrow))?
EDIT:
I don't want to use a custom back button because that forces me to disable the swipe/back-gesture in iOS7
EDIT
I think I might have found the trick (in iOS 7 Design Resource -- UIKit User Interface Catalog.)
Under Bar Button Items
Note that a bar button image will be automatically rendered as a template image within a navigation bar, unless you explicitly set its rendering mode to UIImageRenderingModeAlwaysOriginal. For more information, see Template Images.
Under Template Images they have some code to specify the UIImageRenderingMode.
UIImage *myImage = [UIImage imageNamed:#"back"];
UIImage *backButtonImage = [myImage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
// now use the new backButtomImage
[[UINavigationBar appearance] setBackIndicatorImage:backButtonImage];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:backButtonImage];
Try creating the UIImage with alignment insets and then set the Back Indicator image.
UIEdgeInsets insets = UIEdgeInsetsMake(10, 0, 0, 0); // or (0, 0, -10.0, 0)
UIImage *alignedImage = [[UIImage imageNamed:#"back"] imageWithAlignmentRectInsets:insets];
[[UINavigationBar appearance] setBackIndicatorImage:alignedImage];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:alignedImage];
You might also try adjusting the position of the UINavigationBar title text
[[UINavigationBar appearance] setTitleVerticalPositionAdjustment:(CGFloat)adjustment forBarMetrics:(UIBarMetrics)barMetrics];
Well just follow one of the suggestions to fix the layout and lose the iOS 7 "back gesture", and then fix it with a UIScreenEdgePanGestureRecognizer!
A UIScreenEdgePanGestureRecognizer looks for panning (dragging) gestures that start near an edge of the screen. The system uses screen edge gestures in some cases to initiate view controller transitions. You can use this class to replicate the same gesture behavior for your own actions.
PLEASE SEE EDIT BELOW!!!
I created a custom back button in iOS7 not too long ago. Mine has an arrow and the word back on it. I do think pawan's suggestion is a good start. To create the back button with your custom image you can use,
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStylePlain target:self action:#selector(backButtonClicked)];
[backButton setBackgroundImage:finalImage forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
[backButton setTitlePositionAdjustment:UIOffsetMake(-20, 0) forBarMetrics:UIBarMetricsDefault];
self.navigationItem.leftBarButtonItem = backButton;
My image finalImage is a composite of two different images, but you can just use your "back" image. But I think that is where the problem lies. My image was a composite, you might want to make a composite as well, but put a clear space above your back icon. I placed a clear space to the right of my icon to adjust it's spacing. Here is the code,
UIImage *arrow = [UIImage imageNamed:#"back.png"];
UIImage *wordSpace = [UIImage imageNamed:#"whiteSpace.png"];
CGSize size = CGSizeMake(arrow.size.width + wordSpace.size.width, arrow.size.height);
UIGraphicsBeginImageContext(size);
[arrow drawInRect:CGRectMake(0, 0, arrow.size.width, size.height)];
[wordSpace drawInRect:CGRectMake(arrow.size.width, 0, wordSpace.size.width, wordSpace.size.height)];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
The Image wordSpace is a clear png that I made in photoshop so my new back button image was not stretched. You might want to place a clear png on top, to push the icon down a little. Make the size.height of it in photoshop for what you think the adjustment should be. You might need to futz with this a bit. And make sure to change up the CGSize so that it fits your icon and the clear space.
My word back was a bit off, so I looked at
[backButton setTitlePositionAdjustment:UIOffsetMake(-20, 0) forBarMetrics:UIBarMetricsDefault];
I had to play around with that line a bit to make it look as good as possible but it finally gave me what I wanted with the -20. I even adjusted the second variable which is 0 in mine, this moved the actual icon around. -5 put the icon down way to far, but its another option from the clear png.
Now to deal with the fact that you want it to be an actual back button. Look at the first line of code I posted. The action on the button is #selector(backButtonClicked). So all you need to do is make that method and you should be good to go!
- (void)backButtonClicked
{
NSLog(#"going back");
[self.navigationController popViewControllerAnimated:YES];
}
Hope this helps a bit.
EDIT*****
I was playing around with my code a little bit and found a better way to move the back icon. I just used a ship's wheel because I didn't have the same one that you did, but it will work the same.
Since you don't really want a title you can create the button with this code,
UIImage *image = [UIImage imageNamed:#"781-ships-wheel.png"];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:#selector(backButtonClicked)];
Just change the 781 stuff with your icon's name. Then you can move it around with the following,
[backButton setImageInsets:UIEdgeInsetsMake(20, 0, -20, 0)];
Take a look at this picture.
This shows the icon down considerably, but I wanted to show you the idea. The numbers for the Edge insets are Top, Left, Bottom, and Right. Don't touch the left and right if you don't need to move it that way, change the top and bottom. Notice however, that if you need to move it down by 20 points like I did, (way too much) you need to offset in the negative for the bottom, or the icon will get compressed. This is what it looks like with all zero's.
So you can pretty much move it where ever you want, but you will still have to set up the #selector(backButtonClicked) to make it work like the real back button.
This is Swift 2 version.
The simplest way is like this. Put this code in AppDelegate.'
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
let navigationBarAppearace = UINavigationBar.appearance()
let image = UIImage(named: "back-btn")
navigationBarAppearace.backIndicatorImage = image
navigationBarAppearace.backIndicatorTransitionMaskImage = image
return true
}
if your back button has background colour, it may won't work correctly.
Add your icon to asset folder for each resolution like this:
You can try this
self.navigationItem.leftBarButtonItem.imageInsets = UIEdgeInsetsMake(0, 0, 10, 0);
The problem is that your image is too tall. To prove this, first try this code:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(10,20), NO, 0);
CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(6,0,4,20));
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navbar.backIndicatorImage = im;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(10,20), NO, 0);
UIImage* im2 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navbar.backIndicatorTransitionMaskImage = im2;
It looks fine. Now change the 20 to 30 in the two CGSizeMake calls:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(10,30), NO, 0);
CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(6,0,4,20));
UIImage* im = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navbar.backIndicatorImage = im;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(10,30), NO, 0);
UIImage* im2 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.navbar.backIndicatorTransitionMaskImage = im2;
The icon is now too high.
So just make your image 20 pixels tall and all will be well.
UIEdgeInsets insets = UIEdgeInsetsMake(0, 0, -2, 0); // or (2,0,0,0)
UIImage *backArrowImage = [[UIImage imageNamed:#"back"] imageWithAlignmentRectInsets:insets];
[[UINavigationBar appearance] setBackIndicatorImage:backArrowImage];
[[UINavigationBar appearance] setBackIndicatorTransitionMaskImage:backArrowImage];

Fill SKShapeNode with pattern image

I'm trying to fill a SKShapeNode with an Image/pattern but I'm still unsuccessfull.
Can you help me solving this or giving me an alternative? I want to create a collidable custom shape (from any SpriteKit kind) filled with a pattern image.
I've tried the following:
UIBezierPath *path = [[UIBezierPath alloc] init];
[path addArcWithCenter:CGPointMake(0.0, 0.0) radius:50.0 startAngle:0.0 endAngle:(M_PI*2.0) clockwise:YES];
SKShapeNode *shape = [[SKShapeNode alloc] init];
UIImage *patternImg = [UIImage imageNamed:#"pattern"];
shape.path = path.CGPath;
shape.fillColor = [[SKColor alloc] initWithCGColor:[[UIColor alloc] initWithPatternImage:patternImg].CGColor];
and also:
shape.fillColor = [[SKColor alloc] initWithPatternImage:[[UIImage alloc] initWithCGImage:[UIImage imageNamed:#"Basketball"].CGImage]];
This works (but it isn't what I'm looking for):
shape.fillColor = [SKColor redColor];
Thank you!
Starting from iOS 8.0 there is fillTexture property in the SKShapeNode.
i had the sample problem in my game, finally my solution was to add a SKSpriteNode as a child of the SKShapeNode and it worked fine.
SKSpriteNode* node = [[SKSpriteNode alloc] initWithImageNamed:#"bombIcon.png"];
node.name = #"bomb";
node.size = CGSizeMake(10, 10);
[self.bombNode addChild:node];
Where self.bombNode is a SKShapeNode.
Hope it helps
You could try to achieve that with SKCropNode. However, I've seen several questions here that SKShapeNode cannot act as maskNode for SKCropNode, but I haven't tested it myself. In this case you probably have to use SKSpriteNode instead of SKShapeNode.
Well, using modern Swift (you're using Swift by now, right?), you could try:
var marbleNode: SKSpriteNode!
Then later, in your init method:
marbleNode = SKSpriteNode(imageNamed: "SmallerSwirl");
marbleNode.physicsBody = SKPhysicsBody(circleOfRadius: 35.0)
marbleNode.physicsBody?.dynamic = true
marbleNode.physicsBody?.affectedByGravity = true
print(marbleNode.physicsBody)
marbleNode.position = CGPointMake(centerPoint.position.x + 10.0, centerPoint.position.y + 10.0)
self.addChild(marbleNode)
Okay, so that gives us a round sprite node to work with. The Sprite node is responsive to physics, because you set up its physics body separately. So far, so good. Now we need to address the glossed-over part, namely the introduction of the SmallerSwirl .png image.
When you set up your project, it included an Assets.xcassets (pronounced, "x c assets") entry. Click on it, then click on the "+" sign at the middle/bottom of the first column, by the word filter. From the menu that appears, select "New Image Set". A new entry labeled "Image" appears. Click on the word "Image" to change it to "SmallerSwirl".
Next to the SmallerSwirl entry, you see blanks labeled 1x, 2x, and 3x. They are for different screen resolutions. Start by dragging your preferred .png image into the 1x square. That image can be named whatever you want it to be named. It doesn't have to be named SmallerSwirl, though it can be. Drag other images to the 2x and 3x slots if you like.
Run, and you should see your preferred image embodied as a sprite, dancing around the screen.

NSImageView setImageScaling notWorkingCorrectly

I'm having problems scaling an image in nsimageview correctly. What happens is when the image is loaded, it doesn't fill up the entire nsimageview. I used NSScaleToFit and it completely stretched the image. Since I don't know the dimensions of the photo (it changes, depending on what image is used) I can't set the nsimageview to a size and leave it there. What I want to do is fill the entire nsimageview with an image, proportionally, even if some of the image is cut off.
This is the code that I'm using:
NSString *image_path = [applicationSupportDirectory stringByAppendingPathComponent:desktop_name];
NSImage *imageFromBundle = [[NSImage alloc] initWithContentsOfFile:image_path];
[ViewImage setImageScaling:NSScaleProportionally];
[ViewImage setImage: imageFromBundle];
I had the same problem. I wanted to have the image to be scaled to fill but keeping the aspect ratio of the original image. Strangely, this is not as simple as it seems, and does not come out of the box with NSImageView. I wanted the NSImageView scale nicely while it resize with superview(s). I made a drop-in NSImageView subclass you can find on github: KPCScaleToFillNSImageView
I don't think something like this is built-in; you'll likely have to transform the image yourself.
It is relatively straightforward though; you can see an example implementation here.
I made my own solution, since the ones that were built-in didn't work.
NSRect frame = [MyWindow frame];
if (abs(windowHeight-[imageFromBundle size].width) > abs(windowWidth-[imageFromBundle size].height)) {
frame.size.height = windowWidth;
frame.size.width = 1+windowWidth*(([imageFromBundle size].width/[imageFromBundle size].height-(10*pow([imageFromBundle size].width, 2))/(pow([imageFromBundle size].height, 2)* windowHeight)));
} else {
frame.size.width = windowHeight;
frame.size.height = ((windowHeight/[imageFromBundle size].width)*[imageFromBundle size].height);
}
[MyWindow setFrame: frame
display: YES
animate: YES];

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.

Does anyone know how I can get the "real" size of the UIImageView instead of creating a frame

I was hoping there was some sort of function that could take the real size of my picture
CGRect myImageRect = CGRectMake(0.0f, 0.0f, 320.0, 210.0f); // 234
UIImageView *myImage = [[UIImageView alloc] initWithFrame:myImageRect];
[myImage setImage:[UIImage imageNamed:#"start.png"]];
And with CGRectMake which does something like this ..( imageViewHeight ,
CGFloat imageViewHeight = [myImage frame].size.height;
So that I could get the real size instead of having to define it like you can seen above.
I don't really get what you're asking, but here's a shot:
If you have a UIImage, and you want to know its size, you can ask it for its -[UIImage size] property.
However, if you want to create a UIImageView that's the same size as a UIImage, then you can just use -[UIImageView initWithImage:], which will automatically set the frame of the UIImageView to correspond to the dimensions of the image.
If, however, you're just looking to change the dimensions of a currently existing view, there's really no easy way to do that without messing around with the view's frame. You could maybe apply an affine transform to scale it, but it's easier to manipulate the frame.
It looks like you're asking to add the image to the imageview without first creating a frame. If this is the case, you can do the following:
UIImageView *myImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"start.png"]];
As far as I understood, you are looking for the size of the image used in UIImageView object. To do that, there is not a function built in UIImageView but you can do it this way:
NSString* image= [myImage image].accessibilityIdentifier; // Get the image's name
UIImage *img = [UIImage imageNamed:image]; // Create an image object with that name
CGSize size = img.size; // Get the size of image
Hope this helps your question.