├── LICENSE ├── README.md ├── UIImageView+GeometryConversion.h ├── UIImageView+GeometryConversion.m └── UIImageView-GeometryConvesion.swift /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012 Dominique d'Argent 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UIImageView-GeometryConversion 2 | A category on UIImageView that provides methods for converting points and rects from the image to view coordinates and vice versa. 3 | 4 | ## License 5 | This project is licensed under the terms of the MIT license. See the [LICENSE](https://github.com/nubbel/UIImageView-GeometryConversion/blob/master/LICENSE) file. 6 | -------------------------------------------------------------------------------- /UIImageView+GeometryConversion.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+GeometryConversion.h 3 | // 4 | // Created by Dominique d'Argent on 18.04.12. 5 | // Copyright (c) 2012. All rights reserved. 6 | // 7 | // Thomas Sarlandie - 2012: 8 | // - Added convertPointFromView:viewPoint 9 | // - Added convertRectFromView:viewPoint 10 | // 11 | // Contribution released in the public domain. 12 | 13 | #import 14 | #import 15 | 16 | 17 | @interface UIImageView (GeometryConversion) 18 | 19 | - (CGPoint)convertPointFromImage:(CGPoint)imagePoint; 20 | - (CGRect)convertRectFromImage:(CGRect)imageRect; 21 | 22 | - (CGPoint)convertPointFromView:(CGPoint)viewPoint; 23 | - (CGRect)convertRectFromView:(CGRect)viewRect; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /UIImageView+GeometryConversion.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+GeometryConversion.m 3 | // 4 | // Created by Dominique d'Argent on 18.04.12. 5 | // Copyright (c) 2012. All rights reserved. 6 | // 7 | // Thomas Sarlandie - 2012: 8 | // - Added convertPointFromView:viewPoint 9 | // - Added convertRectFromView:viewPoint 10 | // 11 | // Contribution released in the public domain. 12 | 13 | #import "UIImageView+GeometryConversion.h" 14 | 15 | @implementation UIImageView (GeometryConversion) 16 | 17 | - (CGPoint)convertPointFromImage:(CGPoint)imagePoint { 18 | CGPoint viewPoint = imagePoint; 19 | 20 | CGSize imageSize = self.image.size; 21 | CGSize viewSize = self.bounds.size; 22 | 23 | CGFloat ratioX = viewSize.width / imageSize.width; 24 | CGFloat ratioY = viewSize.height / imageSize.height; 25 | 26 | UIViewContentMode contentMode = self.contentMode; 27 | 28 | switch (contentMode) { 29 | case UIViewContentModeScaleToFill: 30 | case UIViewContentModeRedraw: 31 | { 32 | viewPoint.x *= ratioX; 33 | viewPoint.y *= ratioY; 34 | break; 35 | } 36 | 37 | case UIViewContentModeScaleAspectFit: 38 | case UIViewContentModeScaleAspectFill: 39 | { 40 | CGFloat scale; 41 | 42 | if (contentMode == UIViewContentModeScaleAspectFit) { 43 | scale = MIN(ratioX, ratioY); 44 | } 45 | else /*if (contentMode == UIViewContentModeScaleAspectFill)*/ { 46 | scale = MAX(ratioX, ratioY); 47 | } 48 | 49 | viewPoint.x *= scale; 50 | viewPoint.y *= scale; 51 | 52 | viewPoint.x += (viewSize.width - imageSize.width * scale) / 2.0f; 53 | viewPoint.y += (viewSize.height - imageSize.height * scale) / 2.0f; 54 | 55 | break; 56 | } 57 | 58 | case UIViewContentModeCenter: 59 | { 60 | viewPoint.x += viewSize.width / 2.0 - imageSize.width / 2.0f; 61 | viewPoint.y += viewSize.height / 2.0 - imageSize.height / 2.0f; 62 | 63 | break; 64 | } 65 | 66 | case UIViewContentModeTop: 67 | { 68 | viewPoint.x += viewSize.width / 2.0 - imageSize.width / 2.0f; 69 | 70 | break; 71 | } 72 | 73 | case UIViewContentModeBottom: 74 | { 75 | viewPoint.x += viewSize.width / 2.0 - imageSize.width / 2.0f; 76 | viewPoint.y += viewSize.height - imageSize.height; 77 | 78 | break; 79 | } 80 | 81 | case UIViewContentModeLeft: 82 | { 83 | viewPoint.y += viewSize.height / 2.0 - imageSize.height / 2.0f; 84 | 85 | break; 86 | } 87 | 88 | case UIViewContentModeRight: 89 | { 90 | viewPoint.x += viewSize.width - imageSize.width; 91 | viewPoint.y += viewSize.height / 2.0 - imageSize.height / 2.0f; 92 | 93 | break; 94 | } 95 | 96 | case UIViewContentModeTopRight: 97 | { 98 | viewPoint.x += viewSize.width - imageSize.width; 99 | 100 | break; 101 | } 102 | 103 | 104 | case UIViewContentModeBottomLeft: 105 | { 106 | viewPoint.y += viewSize.height - imageSize.height; 107 | 108 | break; 109 | } 110 | 111 | 112 | case UIViewContentModeBottomRight: 113 | { 114 | viewPoint.x += viewSize.width - imageSize.width; 115 | viewPoint.y += viewSize.height - imageSize.height; 116 | 117 | break; 118 | } 119 | 120 | case UIViewContentModeTopLeft: 121 | default: 122 | { 123 | break; 124 | } 125 | } 126 | 127 | return viewPoint; 128 | } 129 | 130 | - (CGRect)convertRectFromImage:(CGRect)imageRect { 131 | CGPoint imageTopLeft = imageRect.origin; 132 | CGPoint imageBottomRight = CGPointMake(CGRectGetMaxX(imageRect), 133 | CGRectGetMaxY(imageRect)); 134 | 135 | CGPoint viewTopLeft = [self convertPointFromImage:imageTopLeft]; 136 | CGPoint viewBottomRight = [self convertPointFromImage:imageBottomRight]; 137 | 138 | CGRect viewRect; 139 | viewRect.origin = viewTopLeft; 140 | viewRect.size = CGSizeMake(ABS(viewBottomRight.x - viewTopLeft.x), 141 | ABS(viewBottomRight.y - viewTopLeft.y)); 142 | 143 | return viewRect; 144 | } 145 | 146 | - (CGPoint)convertPointFromView:(CGPoint)viewPoint { 147 | CGPoint imagePoint = viewPoint; 148 | 149 | CGSize imageSize = self.image.size; 150 | CGSize viewSize = self.bounds.size; 151 | 152 | CGFloat ratioX = viewSize.width / imageSize.width; 153 | CGFloat ratioY = viewSize.height / imageSize.height; 154 | 155 | UIViewContentMode contentMode = self.contentMode; 156 | 157 | switch (contentMode) { 158 | case UIViewContentModeScaleToFill: 159 | case UIViewContentModeRedraw: 160 | { 161 | imagePoint.x /= ratioX; 162 | imagePoint.y /= ratioY; 163 | break; 164 | } 165 | 166 | case UIViewContentModeScaleAspectFit: 167 | case UIViewContentModeScaleAspectFill: 168 | { 169 | CGFloat scale; 170 | 171 | if (contentMode == UIViewContentModeScaleAspectFit) { 172 | scale = MIN(ratioX, ratioY); 173 | } 174 | else /*if (contentMode == UIViewContentModeScaleAspectFill)*/ { 175 | scale = MAX(ratioX, ratioY); 176 | } 177 | 178 | // Remove the x or y margin added in FitMode 179 | imagePoint.x -= (viewSize.width - imageSize.width * scale) / 2.0f; 180 | imagePoint.y -= (viewSize.height - imageSize.height * scale) / 2.0f; 181 | 182 | imagePoint.x /= scale; 183 | imagePoint.y /= scale; 184 | 185 | break; 186 | } 187 | 188 | case UIViewContentModeCenter: 189 | { 190 | imagePoint.x -= (viewSize.width - imageSize.width) / 2.0f; 191 | imagePoint.y -= (viewSize.height - imageSize.height) / 2.0f; 192 | 193 | break; 194 | } 195 | 196 | case UIViewContentModeTop: 197 | { 198 | imagePoint.x -= (viewSize.width - imageSize.width) / 2.0f; 199 | 200 | break; 201 | } 202 | 203 | case UIViewContentModeBottom: 204 | { 205 | imagePoint.x -= (viewSize.width - imageSize.width) / 2.0f; 206 | imagePoint.y -= (viewSize.height - imageSize.height); 207 | 208 | break; 209 | } 210 | 211 | case UIViewContentModeLeft: 212 | { 213 | imagePoint.y -= (viewSize.height - imageSize.height) / 2.0f; 214 | 215 | break; 216 | } 217 | 218 | case UIViewContentModeRight: 219 | { 220 | imagePoint.x -= (viewSize.width - imageSize.width); 221 | imagePoint.y -= (viewSize.height - imageSize.height) / 2.0f; 222 | 223 | break; 224 | } 225 | 226 | case UIViewContentModeTopRight: 227 | { 228 | imagePoint.x -= (viewSize.width - imageSize.width); 229 | 230 | break; 231 | } 232 | 233 | 234 | case UIViewContentModeBottomLeft: 235 | { 236 | imagePoint.y -= (viewSize.height - imageSize.height); 237 | 238 | break; 239 | } 240 | 241 | 242 | case UIViewContentModeBottomRight: 243 | { 244 | imagePoint.x -= (viewSize.width - imageSize.width); 245 | imagePoint.y -= (viewSize.height - imageSize.height); 246 | 247 | break; 248 | } 249 | 250 | case UIViewContentModeTopLeft: 251 | default: 252 | { 253 | break; 254 | } 255 | } 256 | 257 | return imagePoint; 258 | } 259 | 260 | - (CGRect)convertRectFromView:(CGRect)viewRect { 261 | CGPoint viewTopLeft = viewRect.origin; 262 | CGPoint viewBottomRight = CGPointMake(CGRectGetMaxX(viewRect), 263 | CGRectGetMaxY(viewRect)); 264 | 265 | CGPoint imageTopLeft = [self convertPointFromView:viewTopLeft]; 266 | CGPoint imageBottomRight = [self convertPointFromView:viewBottomRight]; 267 | 268 | CGRect imageRect; 269 | imageRect.origin = imageTopLeft; 270 | imageRect.size = CGSizeMake(ABS(imageBottomRight.x - imageTopLeft.x), 271 | ABS(imageBottomRight.y - imageTopLeft.y)); 272 | 273 | return imageRect; 274 | } 275 | 276 | @end 277 | -------------------------------------------------------------------------------- /UIImageView-GeometryConvesion.swift: -------------------------------------------------------------------------------- 1 | extension UIImageView { 2 | 3 | func convertPoint(fromImagePoint imagePoint: CGPoint) -> CGPoint { 4 | guard let imageSize = image?.size else { return CGPoint.zero } 5 | 6 | var viewPoint = imagePoint 7 | let viewSize = bounds.size 8 | 9 | let ratioX = viewSize.width / imageSize.width 10 | let ratioY = viewSize.height / imageSize.height 11 | 12 | switch contentMode { 13 | case .scaleAspectFit: fallthrough 14 | case .scaleAspectFill: 15 | var scale : CGFloat = 0 16 | 17 | if contentMode == .scaleAspectFit { 18 | scale = min(ratioX, ratioY) 19 | } 20 | else { 21 | scale = max(ratioX, ratioY) 22 | } 23 | 24 | viewPoint.x *= scale 25 | viewPoint.y *= scale 26 | 27 | viewPoint.x += (viewSize.width - imageSize.width * scale) / 2.0 28 | viewPoint.y += (viewSize.height - imageSize.height * scale) / 2.0 29 | 30 | case .scaleToFill: fallthrough 31 | case .redraw: 32 | viewPoint.x *= ratioX 33 | viewPoint.y *= ratioY 34 | case .center: 35 | viewPoint.x += viewSize.width / 2.0 - imageSize.width / 2.0 36 | viewPoint.y += viewSize.height / 2.0 - imageSize.height / 2.0 37 | case .top: 38 | viewPoint.x += viewSize.width / 2.0 - imageSize.width / 2.0 39 | case .bottom: 40 | viewPoint.x += viewSize.width / 2.0 - imageSize.width / 2.0 41 | viewPoint.y += viewSize.height - imageSize.height 42 | case .left: 43 | viewPoint.y += viewSize.height / 2.0 - imageSize.height / 2.0 44 | case .right: 45 | viewPoint.x += viewSize.width - imageSize.width 46 | viewPoint.y += viewSize.height / 2.0 - imageSize.height / 2.0 47 | case .topRight: 48 | viewPoint.x += viewSize.width - imageSize.width 49 | case .bottomLeft: 50 | viewPoint.y += viewSize.height - imageSize.height 51 | case .bottomRight: 52 | viewPoint.x += viewSize.width - imageSize.width 53 | viewPoint.y += viewSize.height - imageSize.height 54 | case.topLeft: fallthrough 55 | default: 56 | break 57 | } 58 | 59 | return viewPoint 60 | } 61 | 62 | func convertRect(fromImageRect imageRect: CGRect) -> CGRect { 63 | let imageTopLeft = imageRect.origin 64 | let imageBottomRight = CGPoint(x: imageRect.maxX, y: imageRect.maxY) 65 | 66 | let viewTopLeft = convertPoint(fromImagePoint: imageTopLeft) 67 | let viewBottomRight = convertPoint(fromImagePoint: imageBottomRight) 68 | 69 | var viewRect : CGRect = .zero 70 | viewRect.origin = viewTopLeft 71 | viewRect.size = CGSize(width: abs(viewBottomRight.x - viewTopLeft.x), height: abs(viewBottomRight.y - viewTopLeft.y)) 72 | return viewRect 73 | } 74 | 75 | func convertPoint(fromViewPoint viewPoint: CGPoint) -> CGPoint { 76 | guard let imageSize = image?.size else { return CGPoint.zero } 77 | 78 | var imagePoint = viewPoint 79 | let viewSize = bounds.size 80 | 81 | let ratioX = viewSize.width / imageSize.width 82 | let ratioY = viewSize.height / imageSize.height 83 | 84 | switch contentMode { 85 | case .scaleAspectFit: fallthrough 86 | case .scaleAspectFill: 87 | var scale : CGFloat = 0 88 | 89 | if contentMode == .scaleAspectFit { 90 | scale = min(ratioX, ratioY) 91 | } 92 | else { 93 | scale = max(ratioX, ratioY) 94 | } 95 | 96 | // Remove the x or y margin added in FitMode 97 | imagePoint.x -= (viewSize.width - imageSize.width * scale) / 2.0 98 | imagePoint.y -= (viewSize.height - imageSize.height * scale) / 2.0 99 | 100 | imagePoint.x /= scale; 101 | imagePoint.y /= scale; 102 | 103 | case .scaleToFill: fallthrough 104 | case .redraw: 105 | imagePoint.x /= ratioX 106 | imagePoint.y /= ratioY 107 | case .center: 108 | imagePoint.x -= (viewSize.width - imageSize.width) / 2.0 109 | imagePoint.y -= (viewSize.height - imageSize.height) / 2.0 110 | case .top: 111 | imagePoint.x -= (viewSize.width - imageSize.width) / 2.0 112 | case .bottom: 113 | imagePoint.x -= (viewSize.width - imageSize.width) / 2.0 114 | imagePoint.y -= (viewSize.height - imageSize.height); 115 | case .left: 116 | imagePoint.y -= (viewSize.height - imageSize.height) / 2.0 117 | case .right: 118 | imagePoint.x -= (viewSize.width - imageSize.width); 119 | imagePoint.y -= (viewSize.height - imageSize.height) / 2.0 120 | case .topRight: 121 | imagePoint.x -= (viewSize.width - imageSize.width); 122 | case .bottomLeft: 123 | imagePoint.y -= (viewSize.height - imageSize.height); 124 | case .bottomRight: 125 | imagePoint.x -= (viewSize.width - imageSize.width) 126 | imagePoint.y -= (viewSize.height - imageSize.height) 127 | case.topLeft: fallthrough 128 | default: 129 | break 130 | } 131 | 132 | return imagePoint 133 | } 134 | 135 | func convertRect(fromViewRect viewRect : CGRect) -> CGRect { 136 | let viewTopLeft = viewRect.origin 137 | let viewBottomRight = CGPoint(x: viewRect.maxX, y: viewRect.maxY) 138 | 139 | let imageTopLeft = convertPoint(fromImagePoint: viewTopLeft) 140 | let imageBottomRight = convertPoint(fromImagePoint: viewBottomRight) 141 | 142 | var imageRect : CGRect = .zero 143 | imageRect.origin = imageTopLeft 144 | imageRect.size = CGSize(width: abs(imageBottomRight.x - imageTopLeft.x), height: abs(imageBottomRight.y - imageTopLeft.y)) 145 | return imageRect 146 | } 147 | 148 | } 149 | --------------------------------------------------------------------------------