[IOS] detailed explanation of partial image stretching + partial image shrinking, ios stretching

Source: Internet
Author: User

[IOS] detailed explanation of partial image stretching + partial image shrinking, ios stretching

(The figure shows 『+"Effect)

When I was still developing WP7, I learned from my IOS colleagues about the implementation of similar functions.

The total height varies depending on the number of items. Therefore, you need to partially stretch the background image to the response height and keep the triangle shape above it unchanged.

However, looking back at WP, there is no API to do this for the image, as long as the image display ratio is different from the source image ratio, it will cause the image to be stretched and deformed.

(So I can only let the design give a triangle in the upper right corner, followed by a solid color rectangle, the solid color rectangle will not be problematic after stretching. If you want to change the image locally, You have to process the pixels by yourself)


 1. Local stretch

Now let's take a look at how to perform partial image stretching. The related API is as follows:

-(UIImage *) resizableImageWithCapInsets :( UIEdgeInsets) capInsets resizingMode :( UIImageResizingMode) resizingMode;

CapInsets defines the image's no-stretch range (this range is relative to the source image size). resizingMode defines the image's transformation in the way of stretching/tiled.


After a four-week no-stretch range is set, the blue part in the middle is stretched/tiled.


1. Let's first discuss stretching based on a certain point.

The original image size is 200*78. You need to stretch it to 200*250, and the width remains unchanged.

①. The effect we get without local stretching:

②. We can know that none of the images can be stretched to achieve the effect. Now we can stretch a point in the middle.

-(Void) viewDidLoad {[super viewDidLoad]; // you can view the corresponding effect of the source image size after the stretch point is changed by touching the source image. UIImage * originImage = [UIImage imageNamed: @ "wechat"]; // 200*78 originButton = [[UIButton alloc] initWithFrame: CGRectMake (0,200,200, 78)]; originButton. userInteractionEnabled = NO; [originButton setBackgroundImage: originImage forState: UIControlStateNormal]; [self. view addSubview: originButton]; // The scaled image CGFloat width = originImage. size. width/2.0; CGFloat height = originImage. size. height/2.0; UIImage * newImage = [originImage resizableImageWithCapInsets: UIEdgeInsetsMake (height, width, height, width) resizingMode: UIImageResizingModeStretch]; // obtain a point in the center, tensile resizableButton = [[UIButton alloc] initWithFrame: CGRectMake (205,200,200,250)]; // The height changes from 78 to 250 [resizableButton setBackgroundImage: originImage forState: UIControlStateNormal]; [self. view addSubview: resizableButton];} // implement touch. If the source image on the left is located, stretch the image based on the position of the touch point-(void) touchesMoved :( NSSet <UITouch *> *) touches withEvent :( UIEvent *) event {UITouch * touch = [touches anyObject]; CGPoint point = [touch locationInView: self. view]; CGPoint actualPoint = [self. view convertPoint: point toView: originButton]; // if (actualPoint. x> = 0 & actualPoint. x <= originButton. frame. size. width & actualPoint. y> = 0 & actualPoint. y <= originButton. frame. size. height) {NSLog (@ "-------- % @ ---------", NSStringFromCGPoint (actualPoint); UIImage * image1 = [UIImage imageNamed: @ "wechat"]; CGFloat top = actualPoint. y; CGFloat left = actualPoint. x; CGFloat bottom = image1.size. height-actualPoint. y; CGFloat right = image1.size. width-actualPoint. x; UIImage * newImage = [image1 success: UIEdgeInsetsMake (top, left, bottom, right) resizingMode: Success]; [resizableButton setBackgroundImage: newImage forState: UIControlStateNormal];}



③. When the width is greater than the actual width of the image:

④. When the length and width are greater than the image, the horizontal vertical direction will be stretched.

It is equivalent to continuing to be horizontally stretched from the stretch point on the top of the vertical stretch end (also stretched at the same time.


Conclusion: All of the above are based on one point for stretching.

During vertical stretching, the line formed by horizontal extension of the stretching point is stretched to the new height.

The line formed by the vertical extension of the stretch point during horizontal stretching.ToNew width.



2. Now let's take a look at stretching based on a certain area.

①. The width remains the same, the height increases, and the Stretch is stretched.

 ②. The height and width are increased, and Tile is used.

Also better explained the above Stretch


Ii. Partial image shrinking

However, if the widget is smaller than the image size, the image will be compressed. Triangle Area is particularly obvious


Since the image can be partially stretched, can the image be partially compressed?


After thinking for a long time, I couldn't find a solution by stretching resizableImageWithCapInsets, but I wrote it myself.


1. You can only contract the part either horizontally or vertically. Therefore, you need a UIEdgeInsets, just like stretching.

2. Cut down the scaled part and make it smaller. Therefore, you need to know the width and height after the change, that is, the final width and height CGRect of the image.

3. This local contraction process is the process of cropping, shrinking, and splicing images.

For convenience, I wrote a classification, which is similar to the stretching method. // capInsets do not need to be stretched.

// The size to be displayed for actualSize-(UIImage *) shrinkImageWithCapInsets :( UIEdgeInsets) capInsets actualSize :( CGSize) actualSize {UIImage newImage = self; if (actualSize. width <self. size. width) {// The width is reduced by newImage = cropping-center shrinking-stitching (newImage); // the code can be divided into three columns at most. For details, see the demo at the end of this article.
If (actualSize. height> = self. size. height) {return newAllImage;} // otherwise, perform vertical processing.} if (actualSize. height <self. size. height) {// The height is reduced by newImage = cropping-center contraction-stitching (newImage); // a maximum of three lines can be divided. For details, see the demo at the end of this article.
return newAllImage; } return nil; }

Image cropping:

// Crop an image-(UIImage *) clipImageWithClipRect :( CGRect) clipRect {CGImageRef clipImageRef = CGImageCreateWithImageInRect (self. CGImage, clipRect); UIGraphicsBeginImageContext (clipRect. size); // set the image size CGContextRef context = gradient (); CGContextDrawImage (context, clipRect, clipImageRef); UIImage * clipImage = [UIImage imageWithCGImage: clipImageRef]; reverse (); return clipImage ;}

Image shrinking:

// Scale the image to a certain size (UIImage *) scaleImageToSize :( CGSize) size {UIGraphicsBeginImageContext (size); // set the new size [self drawInRect: CGRectMake (0, 0, 0, size. width, size. height)]; UIImage * scaleImage = UIGraphicsGetImageFromCurrentImageContext (); UIGraphicsEndImageContext (); return scaleImage ;}

Splice multiple images:

+ (UIImage *) combineWithImages :( NSArray *) images orientation :( partial) orientation {NSMutableArray * sizeArray = [[NSMutableArray alloc] init]; CGFloat maxHeight = 0, maxWidth = 0; for (id image in images) {// if ([image isKindOfClass: [UIImage class]) {CGSize size = (UIImage *) image ). size; if (orientation = YFImageCombineHorizental) {// horizontal maxWidth + = size. width; maxHeight = (size. height> m AxHeight )? Size. height: maxHeight;} else {maxHeight + = size. height; maxWidth = (size. width> maxWidth )? Size. width: maxWidth;} [sizeArray addObject: [NSValue valueWithCGSize: size]; //} CGFloat lastLength = 0; // record the UIGraphicsBeginImageContext (CGSizeMake (maxWidth, maxHeight); for (int I = 0; I <sizeArray. count; I ++) {CGSize size = [[sizeArray objectAtIndex: I] CGSizeValue]; CGRect currentRect; if (orientation = Hangzhou) {// horizontal currentRect = CGRectMake (lastLength, (maxHeight-size. height)/2.0, size. width, size. height); [[images objectAtIndex: I] drawInRect: currentRect]; lastLength = CGRectGetMaxX (currentRect);} else {currentRect = CGRectMake (maxWidth-size. width)/2.0, lastLength, size. width, size. height); [[images objectAtIndex: I] drawInRect: currentRect]; lastLength = CGRectGetMaxY (currentRect) ;}} UIImage * combinedImage = Merge (); merge (); return inecombdimage ;}

Use: Introduce the header file # import "UIImage + YFShrink. h"

// The actual size of the scaled image 150*70 must be input. // The actual display width must be actualWidth <= left + right; // The actual display height must be actualHeight <= top + bottom; UIImage * originImage = [UIImage imageNamed: @ "wechat"]; // 200*78 UIImage * shrinkImage = [originImage shrinkImageWithCapInsets: UIEdgeInsetsMake (30, 40, 30, 60) actualSize: CGSizeMake (150, 60)]; shrinkButton = [[UIButton alloc] initWithFrame: CGRectMake (20,320,150, 60)]; [shrinkButton setBackgroundImage: shrinkImage forState: UIControlStateNormal]; [self. view addSubview: shrinkButton];


Effect: Note:


Github Link

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.