UIImageView with 1 pixel wide and 480 high gradient image - ios

I want to have gradient in my application, and my designer has made me a gradient image that is 1 pixel wide and 480 in height. How do I use this to make UIImageView stretched to full screen to make a fullscreen gradient image?
These two do not work, I get grey screen all the time:
myImageView.image = [UIImage imageNamed:#"gradient.png"];
myImageView.image = [[UIImage imageNamed:#"gradient.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(480, 1, 0, 1)];

myImageView.image = [[UIImage imageNamed:#"gradient.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0.f, 0.f, 0.f, 0.f)];
Just fix UIEdgeInsets

You should use this method, and pass UIEdgeInsetsZero:
myImageView.image = [[UIImage imageNamed:#"gradient.png"] resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeStretch];

Using colorWithPatternImage: is easy for this:
[[self view] setBackgroundColor:[UIColor colorWithPatternImage:gradientImage]]

Related

The Image Size Issue Coming From Server In IOS

I am working on application in which the images are coming from server which i have to display in UIImageview which size is of screen size. the problem is some image resolution are very bigger. So, when I use AspectFill it does not appear properly, it is getting shrink and when I use AspectFit it appears in rectangle shape in image view . so is there any way to display image in UIImageView without getting shrink and without getting croped.
Thanks in advance
I think changing contentMode to UIViewContentModeScaleToFill of your imageView should help:
yourImageView.image = yourImage;
yourImageView.contentMode = UIViewContentModeScaleToFill;
CGRect frame = someImageView.frame;
frame.size = yourImage.size;
yourImageView.frame = frame;
Try this
-(UIImage*)resizeImage:(UIImage *)image imageSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0,0,size.width,size.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
//here is the scaled image which has been changed to the size specified
UIGraphicsEndImageContext();
return newImage;
}
And then use new image for your imageView
You can set image using
UIImage * image=[UIImage imageNamed:#"image.png"];
CGSize size=CGSizeMake(50, 63);//set the width and height
UIImage resizedImage= [self resizeImage:image imageSize:size];
Hope it helps.
try :
UIImageView *yourImageView = [[UIImageView alloc] initWithFrame:CGRectMake(x, y, width, height)];
yourImageView.contentMode = UIViewContentModeRedraw;
yourImageView.image = yourImage;
i hope it helps.

UIView drawViewHierarchyInRect giving pixelated results?

I'm using -drawViewHierarchyInRect:afterScreenUpdates: to draw a view into a UIImage, but it seems no matter what I do the results is always a very low resolution, because the image seems to need to be the same size as the original view?
The UIView is the size of the screen (in this case, 375 x 667), and the content scale factor is 2.0f.
But when I use -drawViewHierarchyInRect:afterScreenUpdates: to draw the view onto the image, it is resized (horribly) to this resolution, even though the contents is a much higher resolution.
I'm using UIGraphicsBeginImageContextWithOptions with a scale of 0.0 to create the image, so I assumed it should draw nicely, but no go. How do you draw the view hierarchy and not lose the detail?
Edit:
Here's some example code (from the answer below, which is giving the same result). It's giving me terribly down-scaled results when trying to draw the UIView hierarchy which includes a high res image:
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0);
[self.view drawViewHierarchyInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) afterScreenUpdates:NO];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
imgView.frame = self.view.bounds;
[self.view addSubview:imgView];
[self.view bringSubviewToFront:imgView];
This code works perfectly. It takes screenshot of current view and puts it to new created UIImageView. Please check that
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, NO, 0);
[self.view drawViewHierarchyInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) afterScreenUpdates:NO];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
imgView.frame = self.view.bounds;
[self.view addSubview:imgView];
[self.view bringSubviewToFront:imgView];

Low quality UIImage after clipping it to a circle

I am trying to clip a UIImage to make it circular, I am starting with a 140*140px image and then running this code:
//round the image
UIImageView *roundView = [[UIImageView alloc] initWithImage:smallImage];
UIGraphicsBeginImageContextWithOptions(roundView.bounds.size, NO, 1.0);
[[UIBezierPath bezierPathWithRoundedRect:roundView.bounds
cornerRadius:roundView.frame.size.width/2] addClip];
[smallImage drawInRect:roundView.bounds];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
smallImage = finalImage;
//end round image
This works as desired but the quality is very low, the image looks fuzzy and the edges around the circle are jagged. I want to achieve them same affect as:
image.layer.cornerRadius = self.thumbnailView.frame.size.width / 2;
image.clipsToBounds = YES;
Not sure why the quality of the image is so low. Can someone give me some pointers please?
You might want to keep scale at 0.f, so it matches the device scale (retina / not retina).
UIGraphicsBeginImageContextWithOptions(roundView.bounds.size, NO, 0.f);
You can do also draw a circle like this:
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.f);
CGRect interiorBox = CGRectInset(rect, 0.f, 0.f);
UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:insideBox];
[bezierPath addClip];
[image drawInRect:rect];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
You are passing the wrong scale in to UIGraphicsBeginImageContextWithOptions. You are passing 1. Use UIGraphicsBeginImageContextWithOptions(roundView.bounds.size, NO, [UIScreen mainScreen].scale);
Are you sure you actually need to do this to the actual image? Would it not be enough to just make the image view rounded?
You can do this very easily.
UIImageView *imageView = // your image view with the image
imageView.frame = CGRectMake(0, 0, 140, 140); // the size you want
imageView.clipsToBounds = YES;
imageView.contentMode = UIViewContentModeScaleAspectFill;
imageView.layer.cornerRadius = 70; // make the corner radius half of the size
This will display your image cropped into a circle by the image view.
The image remains the same. It is just the display of the image that is rounded.
It's much less expensive too (time and memory).
Doing this in a table will not slow it down. You only need to do this once for each of the dequeued cells. For reused cells you do not need to do this as it is done when the cell is first created.

Resizable UIImage

I know this topic has lots of Q&A, I read them all and still couldn't get it going...
I'm trying to stretch an image, while keeping its rounded edges.
This is my image (104x77px):
this is the code I'm using:
UIImage *bg = [UIImage imageNamed:#"btnBg"];
UIEdgeInsets insets = UIEdgeInsetsMake((bg.size.height - 1)/2, (bg.size.width - 1)/2, (bg.size.height - 1)/2, (bg.size.width - 1)/2);
bg = [bg resizableImageWithCapInsets:insets];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20, 50, 44)];
imgView.image = bg;
UIImageView *imgView2 = [[UIImageView alloc] initWithFrame:CGRectMake(20, 70, 250, 44)];
imgView2.image = bg;
[self.view addSubview:imgView];
[self.view addSubview:imgView2];
and this is the problem:
As you can see each image has different edges.
What am I doing wrong?!
I think what you are looking for is a stretchable image
[[UIImage imageNamed:#"someimage.png"] stretchableImageWithLeftCapWidth:5 topCapHeight:5];
As maddy points out this is deprecated in iOS 5, for those of us poor souls having to support iOS 4.3 this is what we use.
Whenever any scaling is involved, images of two different dimensions can't look quite the same. However you can break your image into three parts: the left corners, the middle section (just the parallel lines), and the right corners.
Now to create image views of different sizes, you'll keep the left and right parts constant, and scale the middle section, which won't look distorted as long as you keep the heights constant.
Note that I have give the height of fitInRect as 77 because that's the original image height. You can change this to, say, 44 but keep the number constant for all image views.
Finally, widthToPreserve HAS to be a minimum of 34 (which means the overall Rect width has to be 68 or more) because that's the width of the rounded edge in the original image.
Of course, you can simply all this by having a smaller image, if your target image view height is 44.
This code works:
-(void)viewDidAppear:(BOOL)animated
{
UIImage *img = [UIImage imageNamed:#"img"];
UIImageView *view1 = [self getImageViewFromImage:img widthToPreserve:34 fitInRect:CGRectMake(20, 20, 100, 77)];
UIImageView *view2 = [self getImageViewFromImage:img widthToPreserve:34 fitInRect:CGRectMake(20, 120, 250, 77)];
[self.view addSubview:view1];
[self.view addSubview:view2];
}
-(UIImageView*)getImageViewFromImage:(UIImage*)image widthToPreserve:(float)width fitInRect:(CGRect)rect
{
CGImageRef left, middle, right;
CGRect leftRect, middleRect, rightRect;
UIImage *leftImage, *middleImage, *rightImage;
UIImageView *leftView, *middleView, *rightView;
// calculate CGRect values for the original image
leftRect = CGRectMake(0, 0, width, image.size.height);
middleRect = CGRectMake(width, 0, image.size.width - 2*width, image.size.height);
rightRect = CGRectMake(image.size.width - width, 0, width, image.size.height);
left = CGImageCreateWithImageInRect([image CGImage], leftRect);
middle = CGImageCreateWithImageInRect([image CGImage], middleRect);
right = CGImageCreateWithImageInRect([image CGImage], rightRect);
leftImage = [UIImage imageWithCGImage:left];
middleImage = [UIImage imageWithCGImage:middle];
rightImage = [UIImage imageWithCGImage:right];
leftView = [[UIImageView alloc] initWithImage:leftImage];
middleView = [[UIImageView alloc] initWithImage:middleImage];
rightView = [[UIImageView alloc] initWithImage:rightImage];
//make your image subviews, with scaling on the middle view
[leftView setFrame:CGRectMake(0, 0, width, rect.size.height)];
[middleView setFrame:CGRectMake(width, 0, rect.size.width - 2*width, rect.size.height)];
[rightView setFrame:CGRectMake(rect.size.width - width, 0, width, rect.size.height)];
//add your 3 subviews into a single image view
UIImageView *imgView = [[UIImageView alloc] initWithFrame:rect];
[imgView addSubview:leftView];
[imgView addSubview:middleView];
[imgView addSubview:rightView];
CGImageRelease(left);
CGImageRelease(middle);
CGImageRelease(right);
return imgView;
}
Screenshot:
You can specify the residing mode for your image. The choices are UIImageResizingModeStretch and UIImageResizingModeTile.
The idea of having a stretchable image is so that you can have a small image file. You should consider using a smaller image to save space in your app bundle. Also, your left and right edge insets don't have to be in the middle. They should be just beyond the curve, which looks to be about 40 points in your image.
Here's the code to use to set the resizing mode:
bg = [bg resizableImageWithCapInsets:insets resizingMode: UIImageResizingModeStretch];
Check this out: Resizable UIImage where outside stretches and inside is kept the same
Basically the opposite of what you want. Hope it helps!

How to tile a UIImage vertically while only streching horizontally on iOS?

I have an image that can be stretched in the horizontal direction, but need to be tiled vertically (one on top of the other) to fill my view. How could I do this?
I know that an image can be made resizable by using the -(UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets method. So that works great for the horizontal direction but that method cannot be used for the vertical direction it really needs to be tiled, and not stretched in the vertical direction to work.
Now my idea of how this could work is to run a loop that creates a UIImageView with the horizontally stretched image, and simply adjust the frame.origin.y property, then add it as a subview each loop until I've gone past the height of the view. However this seems like an overly complex way of doing this and really not practical when the view need to be resized (on an iPad rotation for example)
Is there a simpler more efficient way of doing this on iOS 6.x?
I used this to tile an image horizontally in a UIImageView:
UIImage *image = [UIImage imageNamed:#"my_image"];
UIImage *tiledImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0) resizingMode:UIImageResizingModeTile];
UIImageView *imageView = [[UIImageView alloc] initWithImage:tiledImage];
This assumes you set the frame of the UIImageView to a larger size than your image asset. If the height is taller than your image, it will also tile vertically.
Have you considered using UIColor's method colorWithPatternImage: to create a repeating pattern and just pass an image with the correct horizontal width?
Code Example:
// On your desired View Controller
- (void)viewDidLoad
{
[super viewDidLoad];
UIImage *patternImage = [UIImage imageNamed:#"repeating_pattern"];
self.view.backgroundColor = [UIColor colorWithPatternImage:patternImage];
// ... do your other stuff here...
}
UIImage *image = [UIImage imageNamed:#"test.png"];
UIImage *resizableImage = [image resizableImageWithCapInsets:UIEdgeInsetsMake(0, image.size.width / 2, 0, image.size.width / 2)];
So I've figured out a solution for this. It is I think a little jacky but it works.
Basically what I've done was to create my stretchable image with the left and right caps specified. And then I initialize a UIImageView with it. I then adjust the frame of the image view to the desired width. This will appropriately resize the image that is contained within it.
Then finally I used a piece of code I found that creates a new image by vertically tiling the adjusted image that is now contained in the image view. Notice how instead of accessing the original UIImage I am using the UIImageView view's image property.
The last thing then is to set the new UIImage as the patterned background colour of the view
Here is the code:
// create a strechable image
UIImage *image = [[UIImage imageNamed:#"progressBackgroundTop#2x.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 60, 0, 60)];
// create the image view that will contain it
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
CGRect frame = imageView.frame;
frame.size.width = self.view.bounds.size.width;
imageView.frame = frame;
// create the tiled image
CGSize imageViewSize = imageView.bounds.size;
UIGraphicsBeginImageContext(imageViewSize);
CGContextRef imageContext = UIGraphicsGetCurrentContext();
CGContextDrawTiledImage(imageContext, (CGRect){ CGPointZero, imageViewSize }, imageView.image.CGImage);
UIImage *finishedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.view.backgroundColor = [UIColor colorWithPatternImage:finishedImage];

Resources