├── .gitignore ├── LICENSE ├── README.md ├── UIImage+ResizeMagick.h ├── UIImage+ResizeMagick.m └── UIImage-ResizeMagick.podspec /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Without any further information, all the sources provided here are under the MIT License 2 | quoted below. 3 | 4 | Anyway, please contact me by email (vlad.andersen@gmail.com) if you plan to use my work and the provided classes 5 | in your own software. Thanks. 6 | 7 | 8 | /*********************************************************************************** 9 | * 10 | * Copyright (c) 2013 Vlad Andersen 11 | * 12 | * Permission is hereby granted, free of charge, to any person obtaining a copy 13 | * of this software and associated documentation files (the "Software"), to deal 14 | * in the Software without restriction, including without limitation the rights 15 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | * copies of the Software, and to permit persons to whom the Software is 17 | * furnished to do so, subject to the following conditions: 18 | * 19 | * The above copyright notice and this permission notice shall be included in 20 | * all copies or substantial portions of the Software. 21 | * 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | * THE SOFTWARE. 29 | * 30 | *********************************************************************************** 31 | * 32 | * Any comment or suggestion welcome. Referencing this project in your AboutBox is appreciated. 33 | * Please tell me if you use this class so we can cross-reference our projects. 34 | * 35 | ***********************************************************************************/ 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | UIImage-Resize (Magick!) 2 | ======================== 3 | 4 | Resizing UIImage on iOS should be simple. This category provides a simple, yet flexible syntax to resize any image to your needs. 5 | 6 | ```objective-c 7 | - (UIImage *) resizedImageByMagick: (NSString *) spec; 8 | ``` 9 | 10 | where **spec** could be one of the following expressions (follows ImageMagick syntax conventions): 11 | 12 | - [width] -- resize by width, height automatically selected to preserve aspect ratio. 13 | - x[height] -- resize by height, width automagically selected to preserve aspect ratio. 14 | - [width]x[height] -- maximum values of height and width given, aspect ratio preserved. 15 | - [width]x[height]^ -- minimum values of height and width given, aspect ratio preserved. 16 | - [width]x[height]! -- width and height emphatically given, original aspect ratio ignored. 17 | - [width]x[height]# -- scale and crop to exactly that size, original aspect ratio preserved (you probably want this one for your thumbnails). 18 | 19 | Example: 20 | 21 | ```objective-c 22 | UIImage* resizedImage = [image resizedImageByMagick: @"320x320#"]; 23 | ``` 24 | 25 | Installation 26 | ------------ 27 | 28 | [CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries in your projects. See the ["Getting Started" guide for more information](https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking). 29 | 30 | ### Podfile 31 | 32 | ```ruby 33 | pod "UIImage-ResizeMagick" 34 | ``` 35 | 36 | Caveat 37 | ------ 38 | 39 | There is some support for orientations (not mirrored still). There is no support for scale (do we need it?), so please define pixel values. 40 | 41 | The project uses ARC, so you should compile UIImage-Resize.m with ```-fobjc-arc``` if your project is not using ARC. 42 | 43 | Additional methods: 44 | ------------------- 45 | 46 | If you need some resizing with data known on-the-fly, this category defines the following additional methods: 47 | 48 | ```objective-c 49 | - (UIImage *) resizedImageByWidth: (NSUInteger) width; 50 | - (UIImage *) resizedImageByHeight: (NSUInteger) height; 51 | - (UIImage *) resizedImageWithMaximumSize: (CGSize) size; 52 | - (UIImage *) resizedImageWithMinimumSize: (CGSize) size; 53 | ``` 54 | 55 | Adjust interpolation quality: 56 | ----------------------------- 57 | For smooth images try following methods: 58 | 59 | ```objective-c 60 | + (void) setInterpolationQuality: (CGInterpolationQuality) quality; 61 | + (CGInterpolationQuality) interpolationQuality; 62 | ``` 63 | 64 | More information about this option here: 65 | https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGContext/#//apple_ref/c/tdef/CGInterpolationQuality 66 | 67 | ## Donations, anyone? 68 | 69 | If you find UIImage-ResizeMagick useful, I'm accepting Bitcoin donations (who doesn't these days?) at 193bEkLP7zMrNLZm9UdUet4puGD5mQiLai 70 | -------------------------------------------------------------------------------- /UIImage+ResizeMagick.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ResizeMagick.h 3 | // 4 | // 5 | // Created by Vlad Andersen on 1/5/13. 6 | // 7 | // 8 | 9 | 10 | #import 11 | 12 | 13 | @interface UIImage (ResizeMagick) 14 | 15 | + (void) setInterpolationQuality:(CGInterpolationQuality) quality; 16 | + (CGInterpolationQuality) interpolationQuality; 17 | 18 | - (UIImage *) resizedImageByMagick: (NSString *) spec; 19 | - (UIImage *) resizedImageByWidth: (NSUInteger) width; 20 | - (UIImage *) resizedImageByHeight: (NSUInteger) height; 21 | - (UIImage *) resizedImageWithMaximumSize: (CGSize) size; 22 | - (UIImage *) resizedImageWithMinimumSize: (CGSize) size; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /UIImage+ResizeMagick.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ResizeMagick.m 3 | // 4 | // 5 | // Created by Vlad Andersen on 1/5/13. 6 | // 7 | // 8 | 9 | #import "UIImage+ResizeMagick.h" 10 | 11 | static CGInterpolationQuality _interpolationQuality = kCGInterpolationNone; 12 | 13 | @implementation UIImage (ResizeMagick) 14 | 15 | // width Width given, height automagically selected to preserve aspect ratio. 16 | // xheight Height given, width automagically selected to preserve aspect ratio. 17 | // widthxheight Maximum values of height and width given, aspect ratio preserved. 18 | // widthxheight^ Minimum values of width and height given, aspect ratio preserved. 19 | // widthxheight! Exact dimensions, no aspect ratio preserved. 20 | // widthxheight# Crop to this exact dimensions. 21 | 22 | +(void)setInterpolationQuality:(CGInterpolationQuality)quality { 23 | _interpolationQuality = quality; 24 | } 25 | 26 | +(CGInterpolationQuality)interpolationQuality { 27 | return _interpolationQuality; 28 | } 29 | 30 | - (UIImage *) resizedImageByMagick: (NSString *) spec 31 | { 32 | 33 | if([spec hasSuffix:@"!"]) { 34 | NSString *specWithoutSuffix = [spec substringToIndex: [spec length] - 1]; 35 | NSArray *widthAndHeight = [specWithoutSuffix componentsSeparatedByString: @"x"]; 36 | NSUInteger width = labs([[widthAndHeight objectAtIndex: 0] integerValue]); 37 | NSUInteger height = labs([[widthAndHeight objectAtIndex: 1] integerValue]); 38 | UIImage *newImage = [self resizedImageWithMinimumSize: CGSizeMake (width, height)]; 39 | return [newImage drawImageInBounds: CGRectMake (0, 0, width, height)]; 40 | } 41 | 42 | if([spec hasSuffix:@"#"]) { 43 | NSString *specWithoutSuffix = [spec substringToIndex: [spec length] - 1]; 44 | NSArray *widthAndHeight = [specWithoutSuffix componentsSeparatedByString: @"x"]; 45 | NSUInteger width = labs([[widthAndHeight objectAtIndex: 0] integerValue]); 46 | NSUInteger height = labs([[widthAndHeight objectAtIndex: 1] integerValue]); 47 | UIImage *newImage = [self resizedImageWithMinimumSize: CGSizeMake (width, height)]; 48 | return [newImage croppedImageWithRect: CGRectMake ((newImage.size.width - width) / 2, (newImage.size.height - height) / 2, width, height)]; 49 | } 50 | 51 | if([spec hasSuffix:@"^"]) { 52 | NSString *specWithoutSuffix = [spec substringToIndex: [spec length] - 1]; 53 | NSArray *widthAndHeight = [specWithoutSuffix componentsSeparatedByString: @"x"]; 54 | return [self resizedImageWithMinimumSize: CGSizeMake (labs([[widthAndHeight objectAtIndex: 0] integerValue]), 55 | labs([[widthAndHeight objectAtIndex: 1] integerValue]))]; 56 | } 57 | 58 | NSArray *widthAndHeight = [spec componentsSeparatedByString: @"x"]; 59 | if ([widthAndHeight count] == 1) { 60 | return [self resizedImageByWidth: [spec integerValue]]; 61 | } 62 | if ([[widthAndHeight objectAtIndex: 0] isEqualToString: @""]) { 63 | return [self resizedImageByHeight: labs([[widthAndHeight objectAtIndex: 1] integerValue])]; 64 | } 65 | return [self resizedImageWithMaximumSize: CGSizeMake (labs([[widthAndHeight objectAtIndex: 0] integerValue]), 66 | labs([[widthAndHeight objectAtIndex: 1] integerValue]))]; 67 | } 68 | 69 | - (CGImageRef) CGImageWithCorrectOrientation CF_RETURNS_RETAINED 70 | { 71 | if (self.imageOrientation == UIImageOrientationDown) { 72 | //retaining because caller expects to own the reference 73 | CGImageRef cgImage = [self CGImage]; 74 | CGImageRetain(cgImage); 75 | return cgImage; 76 | } 77 | UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0); 78 | 79 | CGContextRef context = UIGraphicsGetCurrentContext(); 80 | CGContextSetInterpolationQuality(context, _interpolationQuality); 81 | 82 | if (self.imageOrientation == UIImageOrientationRight) { 83 | CGContextRotateCTM (context, 90 * M_PI/180); 84 | } else if (self.imageOrientation == UIImageOrientationLeft) { 85 | CGContextRotateCTM (context, -90 * M_PI/180); 86 | } else if (self.imageOrientation == UIImageOrientationUp) { 87 | CGContextRotateCTM (context, 180 * M_PI/180); 88 | } 89 | 90 | [self drawAtPoint:CGPointMake(0, 0)]; 91 | 92 | CGImageRef cgImage = CGBitmapContextCreateImage(context); 93 | UIGraphicsEndImageContext(); 94 | 95 | return cgImage; 96 | } 97 | 98 | 99 | - (UIImage *) resizedImageByWidth: (NSUInteger) width 100 | { 101 | CGImageRef imgRef = [self CGImageWithCorrectOrientation]; 102 | CGFloat original_width = CGImageGetWidth(imgRef); 103 | CGFloat original_height = CGImageGetHeight(imgRef); 104 | CGFloat ratio = width/original_width; 105 | CGImageRelease(imgRef); 106 | return [self drawImageInBounds: CGRectMake(0, 0, width, round(original_height * ratio))]; 107 | } 108 | 109 | - (UIImage *) resizedImageByHeight: (NSUInteger) height 110 | { 111 | CGImageRef imgRef = [self CGImageWithCorrectOrientation]; 112 | CGFloat original_width = CGImageGetWidth(imgRef); 113 | CGFloat original_height = CGImageGetHeight(imgRef); 114 | CGFloat ratio = height/original_height; 115 | CGImageRelease(imgRef); 116 | return [self drawImageInBounds: CGRectMake(0, 0, round(original_width * ratio), height)]; 117 | } 118 | 119 | - (UIImage *) resizedImageWithMinimumSize: (CGSize) size 120 | { 121 | CGImageRef imgRef = [self CGImageWithCorrectOrientation]; 122 | CGFloat original_width = CGImageGetWidth(imgRef); 123 | CGFloat original_height = CGImageGetHeight(imgRef); 124 | CGFloat width_ratio = size.width / original_width; 125 | CGFloat height_ratio = size.height / original_height; 126 | CGFloat scale_ratio = width_ratio > height_ratio ? width_ratio : height_ratio; 127 | CGImageRelease(imgRef); 128 | return [self drawImageInBounds: CGRectMake(0, 0, round(original_width * scale_ratio), round(original_height * scale_ratio))]; 129 | } 130 | 131 | - (UIImage *) resizedImageWithMaximumSize: (CGSize) size 132 | { 133 | CGImageRef imgRef = [self CGImageWithCorrectOrientation]; 134 | CGFloat original_width = CGImageGetWidth(imgRef); 135 | CGFloat original_height = CGImageGetHeight(imgRef); 136 | CGFloat width_ratio = size.width / original_width; 137 | CGFloat height_ratio = size.height / original_height; 138 | CGFloat scale_ratio = width_ratio < height_ratio ? width_ratio : height_ratio; 139 | CGImageRelease(imgRef); 140 | return [self drawImageInBounds: CGRectMake(0, 0, round(original_width * scale_ratio), round(original_height * scale_ratio))]; 141 | } 142 | 143 | - (UIImage *) drawImageInBounds: (CGRect) bounds 144 | { 145 | UIGraphicsBeginImageContextWithOptions(bounds.size, NO, 0.0); 146 | CGContextRef context = UIGraphicsGetCurrentContext(); 147 | CGContextSetInterpolationQuality(context, _interpolationQuality); 148 | [self drawInRect: bounds]; 149 | UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext(); 150 | UIGraphicsEndImageContext(); 151 | return resizedImage; 152 | } 153 | 154 | - (UIImage*) croppedImageWithRect: (CGRect) rect { 155 | 156 | UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0); 157 | CGContextRef context = UIGraphicsGetCurrentContext(); 158 | CGContextSetInterpolationQuality(context, _interpolationQuality); 159 | CGRect drawRect = CGRectMake(-rect.origin.x, -rect.origin.y, self.size.width, self.size.height); 160 | CGContextClipToRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height)); 161 | [self drawInRect:drawRect]; 162 | UIImage* subImage = UIGraphicsGetImageFromCurrentImageContext(); 163 | UIGraphicsEndImageContext(); 164 | 165 | return subImage; 166 | } 167 | 168 | 169 | @end 170 | -------------------------------------------------------------------------------- /UIImage-ResizeMagick.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "UIImage-ResizeMagick" 4 | s.version = "0.0.2" 5 | s.summary = "Resizing UIImage on iOS. ImageMagick-style." 6 | 7 | s.description = <<-DESC 8 | Resizing UIImage on iOS should be simple. This category 9 | provides a simple, yet flexible syntax to resize any image 10 | to your needs. 11 | 12 | - (UIImage *) resizedImageByMagick: (NSString *) spec; 13 | 14 | where spec conforms to the ImageMagick syntax conventions 15 | (think Paperclip). 16 | 17 | UIImage* resizedImage = [image resizedImageByMagick: @"320x320#"]; 18 | DESC 19 | 20 | s.homepage = "https://github.com/mustangostang/UIImage-ResizeMagick" 21 | s.license = 'MIT' 22 | 23 | s.author = { "Vlad Andersen" => "vlad.andersen@gmail.com" } 24 | s.platform = :ios, '5.0' 25 | 26 | s.source = { :git => "https://github.com/mustangostang/UIImage-ResizeMagick.git", :tag => "0.0.2" } 27 | s.source_files = '*.{h,m}' 28 | s.requires_arc = true 29 | 30 | end 31 | --------------------------------------------------------------------------------