├── .gitignore ├── ASCIIArtDebugging ├── ASCIIArtCategories │ ├── UIImage+ASCIIConverter.h │ ├── UIImage+ASCIIConverter.m │ ├── UIImageView+ASCIIConverter.h │ └── UIImageView+ASCIIConverter.m ├── ASCIIArtDebugging.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── xcshareddata │ │ │ └── ASCIIArtDebugging.xccheckout │ └── xcuserdata │ │ └── derekselander.xcuserdatad │ │ └── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist ├── ASCIIArtDebugging │ ├── ASCIIArtDebugging-Info.plist │ ├── ASCIIArtDebugging-Prefix.pch │ ├── DSAppDelegate.h │ ├── DSAppDelegate.m │ ├── DSTableViewController.h │ ├── DSTableViewController.m │ ├── Default-568h@2x.png │ ├── Default.png │ ├── Default@2x.png │ ├── Main.storyboard │ ├── UIImage+ASCIIConverter.h │ ├── UIImage+ASCIIConverter.m │ ├── UIImageView+ASCIIConverter.h │ ├── UIImageView+ASCIIConverter.m │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m ├── BigImage.jpg ├── FuturamaMeme.jpg ├── SmallImage.jpeg └── meme.png ├── README.md └── ScreenShot.png /.gitignore: -------------------------------------------------------------------------------- 1 | /ASCIIArtDebugging/.DS_Store 2 | /.DS_Store 3 | /ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj/xcuserdata/derekselander.xcuserdatad/xcschemes/xcschememanagement.plist 4 | /ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj/xcuserdata/derekselander.xcuserdatad/xcschemes/ASCIIArtDebugging.xcscheme 5 | /ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj/xcuserdata/derekselander.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist 6 | /ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj/project.xcworkspace/xcuserdata/derekselander.xcuserdatad/UserInterfaceState.xcuserstate 7 | /ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj/project.xcworkspace/contents.xcworkspacedata -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtCategories/UIImage+ASCIIConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ASCIIConverter.h 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/4/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (ASCIIConverter) 12 | - (NSString *)description; 13 | - (NSString *)debugDescription; 14 | @end 15 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtCategories/UIImage+ASCIIConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ASCIIConverter.m 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/4/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import "UIImage+ASCIIConverter.h" 10 | 11 | typedef enum { 12 | ALPHA = 0, 13 | BLUE = 1, 14 | GREEN = 2, 15 | RED = 3 16 | } PIXELS; 17 | 18 | typedef enum { 19 | ASCIIImageTypeDebugOnly, 20 | ASCIIImageTypeLogOnly, 21 | ASCIIImageTypeBoth, 22 | } ASCIIImageType; 23 | 24 | #define kMaxWidth 250.0f //Adjust for console width 25 | #define kMaxHeight 150.0f //Adjust for console height 26 | //Adjust for printing type. i.e. Log for NSLog(@"%@", imageView), po imageView in debugger 27 | static ASCIIImageType asciiDebugType = ASCIIImageTypeDebugOnly; 28 | static NSString * characterMap = @"#@8%Oo\";,'. "; 29 | 30 | @implementation UIImage (ASCIIConverter) 31 | //**************************************************************** 32 | #pragma mark - Public Methods 33 | //**************************************************************** 34 | 35 | - (NSString *)description 36 | { 37 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:self.size.width * self.size.height]; 38 | [ASCIIString appendString:[super description]]; 39 | 40 | if (!self) { 41 | [ASCIIString appendString:@"Image is nil!"]; 42 | return ASCIIString; 43 | } else if (asciiDebugType == ASCIIImageTypeBoth || 44 | asciiDebugType == ASCIIImageTypeLogOnly) { 45 | [ASCIIString appendString:@"\n"]; 46 | [ASCIIString appendString:[self convertToASCII]]; 47 | [ASCIIString appendString:@"\n"]; 48 | } 49 | 50 | return (NSString *)ASCIIString; 51 | } 52 | 53 | - (NSString *)debugDescription 54 | { 55 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:self.size.width * self.size.height]; 56 | [ASCIIString appendString:[super description]]; 57 | if (!self) { 58 | [ASCIIString appendString:@"Image is nil!"]; 59 | return ASCIIString; 60 | } else if (asciiDebugType == ASCIIImageTypeBoth || 61 | asciiDebugType == ASCIIImageTypeDebugOnly) { 62 | [ASCIIString appendString:@"\n"]; 63 | [ASCIIString appendString:[self convertToASCII]]; 64 | [ASCIIString appendString:@"\n"]; 65 | } 66 | 67 | return (NSString *)ASCIIString; 68 | } 69 | 70 | //**************************************************************** 71 | #pragma mark - "Private" Methods 72 | //**************************************************************** 73 | 74 | - (NSString *)convertToASCII { 75 | 76 | UIImage *resizedImage = [self resizedImageToFitInSize:CGSizeMake(kMaxHeight, kMaxHeight) scaleIfSmaller:YES]; 77 | CGSize size = resizedImage.size; 78 | int width = size.width; 79 | int height = size.height; 80 | 81 | // the pixels will be painted to this array 82 | uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t)); 83 | 84 | // clear the pixels so any transparency is preserved 85 | memset(pixels, 0, width * height * sizeof(uint32_t)); 86 | 87 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 88 | 89 | // create a context with RGBA pixels 90 | CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8.0f, width * sizeof(uint32_t), colorSpace, 91 | kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); 92 | 93 | // paint the bitmap to our context which will fill in the pixels array 94 | CGContextDrawImage(context, CGRectMake(0, 0, width, height), resizedImage.CGImage); 95 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:width * height + width]; 96 | 97 | for(int y = 0; y < height; y++) { 98 | for(int x = 0; x < width; x++) { 99 | uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x]; 100 | 101 | // convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale 102 | uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; 103 | 104 | NSUInteger position = lroundf((CGFloat)gray * 11.0f/255.0f); 105 | [ASCIIString appendFormat:@"%c", [characterMap characterAtIndex:position]]; 106 | 107 | } 108 | [ASCIIString appendString:@"\n"]; 109 | } 110 | 111 | // we're done with the context, color space, and pixels 112 | CGContextRelease(context); 113 | CGColorSpaceRelease(colorSpace); 114 | free(pixels); 115 | 116 | return [ASCIIString copy]; 117 | } 118 | 119 | -(UIImage*)resizedImageToSize:(CGSize)dstSize 120 | { 121 | CGImageRef imgRef = self.CGImage; 122 | // the below values are regardless of orientation : for UIImages from Camera, width>height (landscape) 123 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which is dependant on the imageOrientation)! 124 | 125 | CGFloat scaleRatio = dstSize.width / srcSize.width; 126 | UIImageOrientation orient = self.imageOrientation; 127 | CGAffineTransform transform = CGAffineTransformIdentity; 128 | switch(orient) { 129 | 130 | case UIImageOrientationUp: //EXIF = 1 131 | transform = CGAffineTransformIdentity; 132 | break; 133 | 134 | case UIImageOrientationUpMirrored: //EXIF = 2 135 | transform = CGAffineTransformMakeTranslation(srcSize.width, 0.0f); 136 | transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 137 | break; 138 | 139 | case UIImageOrientationDown: //EXIF = 3 140 | transform = CGAffineTransformMakeTranslation(srcSize.width, srcSize.height); 141 | transform = CGAffineTransformRotate(transform, M_PI); 142 | break; 143 | 144 | case UIImageOrientationDownMirrored: //EXIF = 4 145 | transform = CGAffineTransformMakeTranslation(0.0, srcSize.height); 146 | transform = CGAffineTransformScale(transform, 1.0f, -1.0f); 147 | break; 148 | 149 | case UIImageOrientationLeftMirrored: //EXIF = 5 150 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 151 | transform = CGAffineTransformMakeTranslation(srcSize.height, srcSize.width); 152 | transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 153 | transform = CGAffineTransformRotate(transform, 3.0f * M_PI_2); 154 | break; 155 | 156 | case UIImageOrientationLeft: //EXIF = 6 157 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 158 | transform = CGAffineTransformMakeTranslation(0.0f, srcSize.width); 159 | transform = CGAffineTransformRotate(transform, 3.0f * M_PI_2); 160 | break; 161 | 162 | case UIImageOrientationRightMirrored: //EXIF = 7 163 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 164 | transform = CGAffineTransformMakeScale(-1.0f, 1.0f); 165 | transform = CGAffineTransformRotate(transform, M_PI_2); 166 | break; 167 | 168 | case UIImageOrientationRight: //EXIF = 8 169 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 170 | transform = CGAffineTransformMakeTranslation(srcSize.height, 0.0f); 171 | transform = CGAffineTransformRotate(transform, M_PI_2); 172 | break; 173 | 174 | default: 175 | [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 176 | 177 | } 178 | 179 | UIGraphicsBeginImageContextWithOptions(dstSize, NO, 0.0f); 180 | 181 | CGContextRef context = UIGraphicsGetCurrentContext(); 182 | 183 | if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 184 | CGContextScaleCTM(context, -scaleRatio, scaleRatio); 185 | CGContextTranslateCTM(context, -srcSize.height, 0.0f); 186 | } else { 187 | CGContextScaleCTM(context, scaleRatio, -scaleRatio); 188 | CGContextTranslateCTM(context, 0.0f, -srcSize.height); 189 | } 190 | 191 | CGContextConcatCTM(context, transform); 192 | 193 | CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0.0f, 0.0f, srcSize.width, srcSize.height), imgRef); 194 | UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext(); 195 | UIGraphicsEndImageContext(); 196 | return resizedImage; 197 | } 198 | 199 | -(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale 200 | { 201 | CGImageRef imgRef = self.CGImage; 202 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); 203 | 204 | UIImageOrientation orient = self.imageOrientation; 205 | switch (orient) { 206 | case UIImageOrientationLeft: 207 | case UIImageOrientationRight: 208 | case UIImageOrientationLeftMirrored: 209 | case UIImageOrientationRightMirrored: 210 | boundingSize = CGSizeMake(boundingSize.height, boundingSize.width); 211 | break; 212 | default: 213 | break; 214 | } 215 | 216 | // Compute the target CGRect in order to keep aspect-ratio 217 | CGSize dstSize; 218 | 219 | if ( !scale && (srcSize.width < boundingSize.width) && (srcSize.height < boundingSize.height) ) { 220 | dstSize = srcSize; 221 | } else { 222 | CGFloat wRatio = boundingSize.width / srcSize.width; 223 | CGFloat hRatio = boundingSize.height / srcSize.height; 224 | 225 | if (wRatio < hRatio) { 226 | dstSize = CGSizeMake(boundingSize.width, floorf(srcSize.height * wRatio)); 227 | } else { 228 | dstSize = CGSizeMake(floorf(srcSize.width * hRatio), boundingSize.height); 229 | } 230 | } 231 | 232 | return [self resizedImageToSize:dstSize]; 233 | } 234 | 235 | @end 236 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtCategories/UIImageView+ASCIIConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+ASCIIConverter.h 3 | // ASCII 4 | // 5 | // Created by Derek Selander on 8/26/12. 6 | // Copyright (c) 2012 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImageView (ASCIIConverter) 12 | - (NSString *)description; 13 | - (NSString *)debugDescription; 14 | @end 15 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtCategories/UIImageView+ASCIIConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+ASCIIConverter.m 3 | // ASCII 4 | // 5 | // Created by Derek Selander on 8/26/12. 6 | // Copyright (c) 2012 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import "UIImageView+ASCIIConverter.h" 10 | 11 | typedef enum { 12 | ALPHA = 0, 13 | BLUE = 1, 14 | GREEN = 2, 15 | RED = 3 16 | } PIXELS; 17 | 18 | typedef enum { 19 | ASCIIImageTypeDebugOnly, 20 | ASCIIImageTypeLogOnly, 21 | ASCIIImageTypeBoth, 22 | } ASCIIImageType; 23 | 24 | #define kMaxWidth 250.0f //Adjust for console width 25 | #define kMaxHeight 150.0f //Adjust for console height 26 | //Adjust for printing type. i.e. Log for NSLog(@"%@", imageView), po imageView in debugger 27 | static ASCIIImageType asciiDebugType = ASCIIImageTypeDebugOnly; 28 | static NSString * characterMap = @"#@8%Oo\";,'. "; 29 | 30 | @implementation UIImageView (ASCIIConverter) 31 | 32 | //**************************************************************** 33 | #pragma mark - Public Methods 34 | //**************************************************************** 35 | 36 | - (NSString *)description 37 | { 38 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:self.image.size.width * self.image.size.height]; 39 | [ASCIIString appendString:[super description]]; 40 | 41 | if (!self.image) { 42 | [ASCIIString appendString:@"Image is nil!"]; 43 | return ASCIIString; 44 | } else if (asciiDebugType == ASCIIImageTypeBoth || 45 | asciiDebugType == ASCIIImageTypeLogOnly) { 46 | [ASCIIString appendString:@"\n"]; 47 | [ASCIIString appendString:[self convertToASCII]]; 48 | [ASCIIString appendString:@"\n"]; 49 | } 50 | 51 | return (NSString *)ASCIIString; 52 | } 53 | 54 | - (NSString *)debugDescription 55 | { 56 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:self.image.size.width * self.image.size.height]; 57 | [ASCIIString appendString:[super description]]; 58 | if (!self.image) { 59 | [ASCIIString appendString:@"Image is nil!"]; 60 | return ASCIIString; 61 | } else if (asciiDebugType == ASCIIImageTypeBoth || 62 | asciiDebugType == ASCIIImageTypeDebugOnly) { 63 | [ASCIIString appendString:@"\n"]; 64 | [ASCIIString appendString:[self convertToASCII]]; 65 | [ASCIIString appendString:@"\n"]; 66 | } 67 | 68 | return (NSString *)ASCIIString; 69 | } 70 | 71 | //**************************************************************** 72 | #pragma mark - "Private" Methods 73 | //**************************************************************** 74 | 75 | - (NSString *)convertToASCII { 76 | 77 | UIImage *resizedImage = [self resizedImageToFitInSize:CGSizeMake(kMaxHeight, kMaxHeight) scaleIfSmaller:YES]; 78 | CGSize size = resizedImage.size; 79 | int width = size.width; 80 | int height = size.height; 81 | 82 | // the pixels will be painted to this array 83 | uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t)); 84 | 85 | // clear the pixels so any transparency is preserved 86 | memset(pixels, 0, width * height * sizeof(uint32_t)); 87 | 88 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 89 | 90 | // create a context with RGBA pixels 91 | CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8.0f, width * sizeof(uint32_t), colorSpace, 92 | kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); 93 | 94 | // paint the bitmap to our context which will fill in the pixels array 95 | CGContextDrawImage(context, CGRectMake(0, 0, width, height), resizedImage.CGImage); 96 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:width * height + width]; 97 | 98 | for(int y = 0; y < height; y++) { 99 | for(int x = 0; x < width; x++) { 100 | uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x]; 101 | 102 | // convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale 103 | uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; 104 | 105 | NSUInteger position = lroundf((CGFloat)gray * 11.0f/255.0f); 106 | [ASCIIString appendFormat:@"%c", [characterMap characterAtIndex:position]]; 107 | 108 | } 109 | [ASCIIString appendString:@"\n"]; 110 | } 111 | 112 | // we're done with the context, color space, and pixels 113 | CGContextRelease(context); 114 | CGColorSpaceRelease(colorSpace); 115 | free(pixels); 116 | 117 | return [ASCIIString copy]; 118 | } 119 | 120 | -(UIImage*)resizedImageToSize:(CGSize)dstSize 121 | { 122 | CGImageRef imgRef = self.image.CGImage; 123 | // the below values are regardless of orientation : for UIImages from Camera, width>height (landscape) 124 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which is dependant on the imageOrientation)! 125 | 126 | CGFloat scaleRatio = dstSize.width / srcSize.width; 127 | UIImageOrientation orient = self.image.imageOrientation; 128 | CGAffineTransform transform = CGAffineTransformIdentity; 129 | switch(orient) { 130 | 131 | case UIImageOrientationUp: //EXIF = 1 132 | transform = CGAffineTransformIdentity; 133 | break; 134 | 135 | case UIImageOrientationUpMirrored: //EXIF = 2 136 | transform = CGAffineTransformMakeTranslation(srcSize.width, 0.0f); 137 | transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 138 | break; 139 | 140 | case UIImageOrientationDown: //EXIF = 3 141 | transform = CGAffineTransformMakeTranslation(srcSize.width, srcSize.height); 142 | transform = CGAffineTransformRotate(transform, M_PI); 143 | break; 144 | 145 | case UIImageOrientationDownMirrored: //EXIF = 4 146 | transform = CGAffineTransformMakeTranslation(0.0, srcSize.height); 147 | transform = CGAffineTransformScale(transform, 1.0f, -1.0f); 148 | break; 149 | 150 | case UIImageOrientationLeftMirrored: //EXIF = 5 151 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 152 | transform = CGAffineTransformMakeTranslation(srcSize.height, srcSize.width); 153 | transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 154 | transform = CGAffineTransformRotate(transform, 3.0f * M_PI_2); 155 | break; 156 | 157 | case UIImageOrientationLeft: //EXIF = 6 158 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 159 | transform = CGAffineTransformMakeTranslation(0.0f, srcSize.width); 160 | transform = CGAffineTransformRotate(transform, 3.0f * M_PI_2); 161 | break; 162 | 163 | case UIImageOrientationRightMirrored: //EXIF = 7 164 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 165 | transform = CGAffineTransformMakeScale(-1.0f, 1.0f); 166 | transform = CGAffineTransformRotate(transform, M_PI_2); 167 | break; 168 | 169 | case UIImageOrientationRight: //EXIF = 8 170 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 171 | transform = CGAffineTransformMakeTranslation(srcSize.height, 0.0f); 172 | transform = CGAffineTransformRotate(transform, M_PI_2); 173 | break; 174 | 175 | default: 176 | [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 177 | 178 | } 179 | 180 | UIGraphicsBeginImageContextWithOptions(dstSize, NO, 0.0f); 181 | 182 | CGContextRef context = UIGraphicsGetCurrentContext(); 183 | 184 | if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 185 | CGContextScaleCTM(context, -scaleRatio, scaleRatio); 186 | CGContextTranslateCTM(context, -srcSize.height, 0.0f); 187 | } else { 188 | CGContextScaleCTM(context, scaleRatio, -scaleRatio); 189 | CGContextTranslateCTM(context, 0.0f, -srcSize.height); 190 | } 191 | 192 | CGContextConcatCTM(context, transform); 193 | 194 | CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0.0f, 0.0f, srcSize.width, srcSize.height), imgRef); 195 | UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext(); 196 | UIGraphicsEndImageContext(); 197 | return resizedImage; 198 | } 199 | 200 | -(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale 201 | { 202 | CGImageRef imgRef = self.image.CGImage; 203 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); 204 | 205 | UIImageOrientation orient = self.image.imageOrientation; 206 | switch (orient) { 207 | case UIImageOrientationLeft: 208 | case UIImageOrientationRight: 209 | case UIImageOrientationLeftMirrored: 210 | case UIImageOrientationRightMirrored: 211 | boundingSize = CGSizeMake(boundingSize.height, boundingSize.width); 212 | break; 213 | default: 214 | break; 215 | } 216 | 217 | // Compute the target CGRect in order to keep aspect-ratio 218 | CGSize dstSize; 219 | 220 | if ( !scale && (srcSize.width < boundingSize.width) && (srcSize.height < boundingSize.height) ) { 221 | dstSize = srcSize; 222 | } else { 223 | CGFloat wRatio = boundingSize.width / srcSize.width; 224 | CGFloat hRatio = boundingSize.height / srcSize.height; 225 | 226 | if (wRatio < hRatio) { 227 | dstSize = CGSizeMake(boundingSize.width, floorf(srcSize.height * wRatio)); 228 | } else { 229 | dstSize = CGSizeMake(floorf(srcSize.width * hRatio), boundingSize.height); 230 | } 231 | } 232 | 233 | return [self resizedImageToSize:dstSize]; 234 | } 235 | 236 | @end 237 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A65AAB6016BDC6AB00B0ED6A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A65AAB5F16BDC6AB00B0ED6A /* UIKit.framework */; }; 11 | A65AAB6216BDC6AB00B0ED6A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A65AAB6116BDC6AB00B0ED6A /* Foundation.framework */; }; 12 | A65AAB6416BDC6AB00B0ED6A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A65AAB6316BDC6AB00B0ED6A /* CoreGraphics.framework */; }; 13 | A65AAB6A16BDC6AB00B0ED6A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = A65AAB6816BDC6AB00B0ED6A /* InfoPlist.strings */; }; 14 | A65AAB6C16BDC6AB00B0ED6A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A65AAB6B16BDC6AB00B0ED6A /* main.m */; }; 15 | A65AAB7016BDC6AB00B0ED6A /* DSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A65AAB6F16BDC6AB00B0ED6A /* DSAppDelegate.m */; }; 16 | A65AAB7216BDC6AB00B0ED6A /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = A65AAB7116BDC6AB00B0ED6A /* Default.png */; }; 17 | A65AAB7416BDC6AB00B0ED6A /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A65AAB7316BDC6AB00B0ED6A /* Default@2x.png */; }; 18 | A65AAB7616BDC6AB00B0ED6A /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A65AAB7516BDC6AB00B0ED6A /* Default-568h@2x.png */; }; 19 | A65AAB8E16BDCF7A00B0ED6A /* UIImageView+ASCIIConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = A65AAB8616BDC6EC00B0ED6A /* UIImageView+ASCIIConverter.m */; }; 20 | A692994619B6CC3800FD265E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A692994519B6CC3800FD265E /* Main.storyboard */; }; 21 | A6A45F1716C0EE0000A273B6 /* UIImage+ASCIIConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = A6A45F1616C0EE0000A273B6 /* UIImage+ASCIIConverter.m */; }; 22 | A6C5172A16BF54280053B3C0 /* BigImage.jpg in Resources */ = {isa = PBXBuildFile; fileRef = A6C5172716BF54280053B3C0 /* BigImage.jpg */; }; 23 | A6C5172B16BF54280053B3C0 /* FuturamaMeme.jpg in Resources */ = {isa = PBXBuildFile; fileRef = A6C5172816BF54280053B3C0 /* FuturamaMeme.jpg */; }; 24 | A6C5172C16BF54280053B3C0 /* SmallImage.jpeg in Resources */ = {isa = PBXBuildFile; fileRef = A6C5172916BF54280053B3C0 /* SmallImage.jpeg */; }; 25 | A6C5173216BF6EE30053B3C0 /* meme.png in Resources */ = {isa = PBXBuildFile; fileRef = A6C5173116BF6EE30053B3C0 /* meme.png */; }; 26 | A6C5173516BF6F3D0053B3C0 /* DSTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A6C5173416BF6F3D0053B3C0 /* DSTableViewController.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | A65AAB5C16BDC6AB00B0ED6A /* ASCIIArtDebugging.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ASCIIArtDebugging.app; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | A65AAB5F16BDC6AB00B0ED6A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 32 | A65AAB6116BDC6AB00B0ED6A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 33 | A65AAB6316BDC6AB00B0ED6A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 34 | A65AAB6716BDC6AB00B0ED6A /* ASCIIArtDebugging-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ASCIIArtDebugging-Info.plist"; sourceTree = ""; }; 35 | A65AAB6916BDC6AB00B0ED6A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 36 | A65AAB6B16BDC6AB00B0ED6A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 37 | A65AAB6D16BDC6AB00B0ED6A /* ASCIIArtDebugging-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ASCIIArtDebugging-Prefix.pch"; sourceTree = ""; }; 38 | A65AAB6E16BDC6AB00B0ED6A /* DSAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DSAppDelegate.h; sourceTree = ""; }; 39 | A65AAB6F16BDC6AB00B0ED6A /* DSAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DSAppDelegate.m; sourceTree = ""; }; 40 | A65AAB7116BDC6AB00B0ED6A /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 41 | A65AAB7316BDC6AB00B0ED6A /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 42 | A65AAB7516BDC6AB00B0ED6A /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 43 | A65AAB8516BDC6EC00B0ED6A /* UIImageView+ASCIIConverter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImageView+ASCIIConverter.h"; sourceTree = ""; }; 44 | A65AAB8616BDC6EC00B0ED6A /* UIImageView+ASCIIConverter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+ASCIIConverter.m"; sourceTree = ""; }; 45 | A692994519B6CC3800FD265E /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 46 | A6A45F1516C0EE0000A273B6 /* UIImage+ASCIIConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+ASCIIConverter.h"; sourceTree = ""; }; 47 | A6A45F1616C0EE0000A273B6 /* UIImage+ASCIIConverter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+ASCIIConverter.m"; sourceTree = ""; }; 48 | A6C5172716BF54280053B3C0 /* BigImage.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = BigImage.jpg; path = ../BigImage.jpg; sourceTree = ""; }; 49 | A6C5172816BF54280053B3C0 /* FuturamaMeme.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = FuturamaMeme.jpg; path = ../FuturamaMeme.jpg; sourceTree = ""; }; 50 | A6C5172916BF54280053B3C0 /* SmallImage.jpeg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = SmallImage.jpeg; path = ../SmallImage.jpeg; sourceTree = ""; }; 51 | A6C5173116BF6EE30053B3C0 /* meme.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = meme.png; path = ../meme.png; sourceTree = ""; }; 52 | A6C5173316BF6F3D0053B3C0 /* DSTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DSTableViewController.h; sourceTree = ""; }; 53 | A6C5173416BF6F3D0053B3C0 /* DSTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DSTableViewController.m; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | A65AAB5916BDC6AB00B0ED6A /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | A65AAB6016BDC6AB00B0ED6A /* UIKit.framework in Frameworks */, 62 | A65AAB6216BDC6AB00B0ED6A /* Foundation.framework in Frameworks */, 63 | A65AAB6416BDC6AB00B0ED6A /* CoreGraphics.framework in Frameworks */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXFrameworksBuildPhase section */ 68 | 69 | /* Begin PBXGroup section */ 70 | A65AAB5316BDC6AB00B0ED6A = { 71 | isa = PBXGroup; 72 | children = ( 73 | A65AAB6516BDC6AB00B0ED6A /* ASCIIArtDebugging */, 74 | A65AAB5E16BDC6AB00B0ED6A /* Frameworks */, 75 | A65AAB5D16BDC6AB00B0ED6A /* Products */, 76 | ); 77 | sourceTree = ""; 78 | }; 79 | A65AAB5D16BDC6AB00B0ED6A /* Products */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | A65AAB5C16BDC6AB00B0ED6A /* ASCIIArtDebugging.app */, 83 | ); 84 | name = Products; 85 | sourceTree = ""; 86 | }; 87 | A65AAB5E16BDC6AB00B0ED6A /* Frameworks */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | A65AAB5F16BDC6AB00B0ED6A /* UIKit.framework */, 91 | A65AAB6116BDC6AB00B0ED6A /* Foundation.framework */, 92 | A65AAB6316BDC6AB00B0ED6A /* CoreGraphics.framework */, 93 | ); 94 | name = Frameworks; 95 | sourceTree = ""; 96 | }; 97 | A65AAB6516BDC6AB00B0ED6A /* ASCIIArtDebugging */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | A65AAB8716BDC6EF00B0ED6A /* ASCIIArtDebuggingCategories */, 101 | A65AAB6E16BDC6AB00B0ED6A /* DSAppDelegate.h */, 102 | A65AAB6F16BDC6AB00B0ED6A /* DSAppDelegate.m */, 103 | A692994519B6CC3800FD265E /* Main.storyboard */, 104 | A6C5173316BF6F3D0053B3C0 /* DSTableViewController.h */, 105 | A6C5173416BF6F3D0053B3C0 /* DSTableViewController.m */, 106 | A65AAB6616BDC6AB00B0ED6A /* Supporting Files */, 107 | ); 108 | path = ASCIIArtDebugging; 109 | sourceTree = ""; 110 | }; 111 | A65AAB6616BDC6AB00B0ED6A /* Supporting Files */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | A65AAB8D16BDC8E300B0ED6A /* Assets */, 115 | A65AAB6716BDC6AB00B0ED6A /* ASCIIArtDebugging-Info.plist */, 116 | A65AAB6816BDC6AB00B0ED6A /* InfoPlist.strings */, 117 | A65AAB6B16BDC6AB00B0ED6A /* main.m */, 118 | A65AAB6D16BDC6AB00B0ED6A /* ASCIIArtDebugging-Prefix.pch */, 119 | A65AAB7116BDC6AB00B0ED6A /* Default.png */, 120 | A65AAB7316BDC6AB00B0ED6A /* Default@2x.png */, 121 | A65AAB7516BDC6AB00B0ED6A /* Default-568h@2x.png */, 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | A65AAB8716BDC6EF00B0ED6A /* ASCIIArtDebuggingCategories */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | A6A45F1516C0EE0000A273B6 /* UIImage+ASCIIConverter.h */, 130 | A6A45F1616C0EE0000A273B6 /* UIImage+ASCIIConverter.m */, 131 | A65AAB8516BDC6EC00B0ED6A /* UIImageView+ASCIIConverter.h */, 132 | A65AAB8616BDC6EC00B0ED6A /* UIImageView+ASCIIConverter.m */, 133 | ); 134 | name = ASCIIArtDebuggingCategories; 135 | sourceTree = ""; 136 | }; 137 | A65AAB8D16BDC8E300B0ED6A /* Assets */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | A6C5173116BF6EE30053B3C0 /* meme.png */, 141 | A6C5172816BF54280053B3C0 /* FuturamaMeme.jpg */, 142 | A6C5172716BF54280053B3C0 /* BigImage.jpg */, 143 | A6C5172916BF54280053B3C0 /* SmallImage.jpeg */, 144 | ); 145 | name = Assets; 146 | sourceTree = ""; 147 | }; 148 | /* End PBXGroup section */ 149 | 150 | /* Begin PBXNativeTarget section */ 151 | A65AAB5B16BDC6AB00B0ED6A /* ASCIIArtDebugging */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = A65AAB8216BDC6AB00B0ED6A /* Build configuration list for PBXNativeTarget "ASCIIArtDebugging" */; 154 | buildPhases = ( 155 | A65AAB5816BDC6AB00B0ED6A /* Sources */, 156 | A65AAB5916BDC6AB00B0ED6A /* Frameworks */, 157 | A65AAB5A16BDC6AB00B0ED6A /* Resources */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | ); 163 | name = ASCIIArtDebugging; 164 | productName = ASCIIArtDebugging; 165 | productReference = A65AAB5C16BDC6AB00B0ED6A /* ASCIIArtDebugging.app */; 166 | productType = "com.apple.product-type.application"; 167 | }; 168 | /* End PBXNativeTarget section */ 169 | 170 | /* Begin PBXProject section */ 171 | A65AAB5416BDC6AB00B0ED6A /* Project object */ = { 172 | isa = PBXProject; 173 | attributes = { 174 | CLASSPREFIX = DS; 175 | LastUpgradeCheck = 0460; 176 | ORGANIZATIONNAME = "Derek Selander"; 177 | }; 178 | buildConfigurationList = A65AAB5716BDC6AB00B0ED6A /* Build configuration list for PBXProject "ASCIIArtDebugging" */; 179 | compatibilityVersion = "Xcode 3.2"; 180 | developmentRegion = English; 181 | hasScannedForEncodings = 0; 182 | knownRegions = ( 183 | en, 184 | ); 185 | mainGroup = A65AAB5316BDC6AB00B0ED6A; 186 | productRefGroup = A65AAB5D16BDC6AB00B0ED6A /* Products */; 187 | projectDirPath = ""; 188 | projectRoot = ""; 189 | targets = ( 190 | A65AAB5B16BDC6AB00B0ED6A /* ASCIIArtDebugging */, 191 | ); 192 | }; 193 | /* End PBXProject section */ 194 | 195 | /* Begin PBXResourcesBuildPhase section */ 196 | A65AAB5A16BDC6AB00B0ED6A /* Resources */ = { 197 | isa = PBXResourcesBuildPhase; 198 | buildActionMask = 2147483647; 199 | files = ( 200 | A65AAB6A16BDC6AB00B0ED6A /* InfoPlist.strings in Resources */, 201 | A65AAB7216BDC6AB00B0ED6A /* Default.png in Resources */, 202 | A65AAB7416BDC6AB00B0ED6A /* Default@2x.png in Resources */, 203 | A65AAB7616BDC6AB00B0ED6A /* Default-568h@2x.png in Resources */, 204 | A692994619B6CC3800FD265E /* Main.storyboard in Resources */, 205 | A6C5172A16BF54280053B3C0 /* BigImage.jpg in Resources */, 206 | A6C5172B16BF54280053B3C0 /* FuturamaMeme.jpg in Resources */, 207 | A6C5172C16BF54280053B3C0 /* SmallImage.jpeg in Resources */, 208 | A6C5173216BF6EE30053B3C0 /* meme.png in Resources */, 209 | ); 210 | runOnlyForDeploymentPostprocessing = 0; 211 | }; 212 | /* End PBXResourcesBuildPhase section */ 213 | 214 | /* Begin PBXSourcesBuildPhase section */ 215 | A65AAB5816BDC6AB00B0ED6A /* Sources */ = { 216 | isa = PBXSourcesBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | A65AAB8E16BDCF7A00B0ED6A /* UIImageView+ASCIIConverter.m in Sources */, 220 | A65AAB6C16BDC6AB00B0ED6A /* main.m in Sources */, 221 | A65AAB7016BDC6AB00B0ED6A /* DSAppDelegate.m in Sources */, 222 | A6C5173516BF6F3D0053B3C0 /* DSTableViewController.m in Sources */, 223 | A6A45F1716C0EE0000A273B6 /* UIImage+ASCIIConverter.m in Sources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXSourcesBuildPhase section */ 228 | 229 | /* Begin PBXVariantGroup section */ 230 | A65AAB6816BDC6AB00B0ED6A /* InfoPlist.strings */ = { 231 | isa = PBXVariantGroup; 232 | children = ( 233 | A65AAB6916BDC6AB00B0ED6A /* en */, 234 | ); 235 | name = InfoPlist.strings; 236 | sourceTree = ""; 237 | }; 238 | /* End PBXVariantGroup section */ 239 | 240 | /* Begin XCBuildConfiguration section */ 241 | A65AAB8016BDC6AB00B0ED6A /* Debug */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | ALWAYS_SEARCH_USER_PATHS = NO; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 246 | CLANG_CXX_LIBRARY = "libc++"; 247 | CLANG_ENABLE_OBJC_ARC = YES; 248 | CLANG_WARN_CONSTANT_CONVERSION = YES; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INT_CONVERSION = YES; 252 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 253 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 254 | COPY_PHASE_STRIP = NO; 255 | GCC_C_LANGUAGE_STANDARD = gnu99; 256 | GCC_DYNAMIC_NO_PIC = NO; 257 | GCC_OPTIMIZATION_LEVEL = 0; 258 | GCC_PREPROCESSOR_DEFINITIONS = ( 259 | "DEBUG=1", 260 | "$(inherited)", 261 | ); 262 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 263 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 264 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 265 | GCC_WARN_UNUSED_VARIABLE = YES; 266 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 267 | ONLY_ACTIVE_ARCH = YES; 268 | SDKROOT = iphoneos; 269 | TARGETED_DEVICE_FAMILY = "1,2"; 270 | }; 271 | name = Debug; 272 | }; 273 | A65AAB8116BDC6AB00B0ED6A /* Release */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | ALWAYS_SEARCH_USER_PATHS = NO; 277 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 278 | CLANG_CXX_LIBRARY = "libc++"; 279 | CLANG_ENABLE_OBJC_ARC = YES; 280 | CLANG_WARN_CONSTANT_CONVERSION = YES; 281 | CLANG_WARN_EMPTY_BODY = YES; 282 | CLANG_WARN_ENUM_CONVERSION = YES; 283 | CLANG_WARN_INT_CONVERSION = YES; 284 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 285 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 286 | COPY_PHASE_STRIP = YES; 287 | GCC_C_LANGUAGE_STANDARD = gnu99; 288 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 289 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 290 | GCC_WARN_UNUSED_VARIABLE = YES; 291 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 292 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 293 | SDKROOT = iphoneos; 294 | TARGETED_DEVICE_FAMILY = "1,2"; 295 | VALIDATE_PRODUCT = YES; 296 | }; 297 | name = Release; 298 | }; 299 | A65AAB8316BDC6AB00B0ED6A /* Debug */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 303 | GCC_PREFIX_HEADER = "ASCIIArtDebugging/ASCIIArtDebugging-Prefix.pch"; 304 | INFOPLIST_FILE = "ASCIIArtDebugging/ASCIIArtDebugging-Info.plist"; 305 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | WRAPPER_EXTENSION = app; 308 | }; 309 | name = Debug; 310 | }; 311 | A65AAB8416BDC6AB00B0ED6A /* Release */ = { 312 | isa = XCBuildConfiguration; 313 | buildSettings = { 314 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 315 | GCC_PREFIX_HEADER = "ASCIIArtDebugging/ASCIIArtDebugging-Prefix.pch"; 316 | INFOPLIST_FILE = "ASCIIArtDebugging/ASCIIArtDebugging-Info.plist"; 317 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 318 | PRODUCT_NAME = "$(TARGET_NAME)"; 319 | WRAPPER_EXTENSION = app; 320 | }; 321 | name = Release; 322 | }; 323 | /* End XCBuildConfiguration section */ 324 | 325 | /* Begin XCConfigurationList section */ 326 | A65AAB5716BDC6AB00B0ED6A /* Build configuration list for PBXProject "ASCIIArtDebugging" */ = { 327 | isa = XCConfigurationList; 328 | buildConfigurations = ( 329 | A65AAB8016BDC6AB00B0ED6A /* Debug */, 330 | A65AAB8116BDC6AB00B0ED6A /* Release */, 331 | ); 332 | defaultConfigurationIsVisible = 0; 333 | defaultConfigurationName = Release; 334 | }; 335 | A65AAB8216BDC6AB00B0ED6A /* Build configuration list for PBXNativeTarget "ASCIIArtDebugging" */ = { 336 | isa = XCConfigurationList; 337 | buildConfigurations = ( 338 | A65AAB8316BDC6AB00B0ED6A /* Debug */, 339 | A65AAB8416BDC6AB00B0ED6A /* Release */, 340 | ); 341 | defaultConfigurationIsVisible = 0; 342 | defaultConfigurationName = Release; 343 | }; 344 | /* End XCConfigurationList section */ 345 | }; 346 | rootObject = A65AAB5416BDC6AB00B0ED6A /* Project object */; 347 | } 348 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj/project.xcworkspace/xcshareddata/ASCIIArtDebugging.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 45DA894A-5F99-40A1-A90F-6882746DEB14 9 | IDESourceControlProjectName 10 | ASCIIArtDebugging 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 9845A74B1D333209976CE4186566764193EE8B17 14 | github.com:DerekSelander/ASCIIArtDebugging.git 15 | 16 | IDESourceControlProjectPath 17 | ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 9845A74B1D333209976CE4186566764193EE8B17 21 | ../../.. 22 | 23 | IDESourceControlProjectURL 24 | github.com:DerekSelander/ASCIIArtDebugging.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 9845A74B1D333209976CE4186566764193EE8B17 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 9845A74B1D333209976CE4186566764193EE8B17 36 | IDESourceControlWCCName 37 | ASCIIArtDebugging 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging.xcodeproj/xcuserdata/derekselander.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/ASCIIArtDebugging-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | selander.com.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIMainStoryboardFile~ipad 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/ASCIIArtDebugging-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ASCIIArtDebugging' target in the 'ASCIIArtDebugging' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 5.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #import "UIImageView+ASCIIConverter.h" 15 | 16 | #ifdef DEBUG 17 | # define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); 18 | #else 19 | # define DLog(...) 20 | #endif 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/DSAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // DSAppDelegate.h 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/2/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DSAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/DSAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // DSAppDelegate.m 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/2/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import "DSAppDelegate.h" 10 | 11 | @implementation DSAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | return YES; 16 | } 17 | 18 | - (void)applicationWillResignActive:(UIApplication *)application 19 | { 20 | } 21 | 22 | - (void)applicationDidEnterBackground:(UIApplication *)application 23 | { 24 | } 25 | 26 | - (void)applicationWillEnterForeground:(UIApplication *)application 27 | { 28 | } 29 | 30 | - (void)applicationDidBecomeActive:(UIApplication *)application 31 | { 32 | } 33 | 34 | - (void)applicationWillTerminate:(UIApplication *)application 35 | { 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/DSTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DSTableViewController.h 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/3/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DSTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/DSTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DSTableViewController.m 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/3/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import "DSTableViewController.h" 10 | 11 | @interface DSTableViewController () 12 | 13 | @end 14 | 15 | @implementation DSTableViewController 16 | 17 | 18 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 19 | { 20 | UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; 21 | 22 | #warning Stick a break point here, then in lldb console type 'po cell.imageView' 23 | 24 | //You can alter the ASCII to also enable/disable ASCIIArt through a NSLog; alter the ASCIIImageViewType; 25 | NSLog(@"%@", cell.imageView); 26 | } 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekSelander/ASCIIArtDebugging/ce30928c0331e6d17e38df7adb58313a314f8c73/ASCIIArtDebugging/ASCIIArtDebugging/Default-568h@2x.png -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekSelander/ASCIIArtDebugging/ce30928c0331e6d17e38df7adb58313a314f8c73/ASCIIArtDebugging/ASCIIArtDebugging/Default.png -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekSelander/ASCIIArtDebugging/ce30928c0331e6d17e38df7adb58313a314f8c73/ASCIIArtDebugging/ASCIIArtDebugging/Default@2x.png -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/UIImage+ASCIIConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ASCIIConverter.h 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/4/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImage (ASCIIConverter) 12 | - (NSString *)description; 13 | - (NSString *)debugDescription; 14 | @end 15 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/UIImage+ASCIIConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImage+ASCIIConverter.m 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/4/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import "UIImage+ASCIIConverter.h" 10 | 11 | typedef enum { 12 | ALPHA = 0, 13 | BLUE = 1, 14 | GREEN = 2, 15 | RED = 3 16 | } PIXELS; 17 | 18 | typedef enum { 19 | ASCIIImageTypeDebugOnly, 20 | ASCIIImageTypeLogOnly, 21 | ASCIIImageTypeBoth, 22 | } ASCIIImageType; 23 | 24 | #define kMaxWidth 75.0f //Adjust for console width 25 | #define kMaxHeight 75.0f //Adjust for console height 26 | //Adjust for printing type. i.e. Log for NSLog(@"%@", imageView), po imageView in debugger 27 | static ASCIIImageType asciiDebugType = ASCIIImageTypeDebugOnly; 28 | static NSString * characterMap = @"#@8%Oo\";,'. "; 29 | 30 | @implementation UIImage (ASCIIConverter) 31 | //**************************************************************** 32 | #pragma mark - Public Methods 33 | //**************************************************************** 34 | 35 | - (NSString *)description 36 | { 37 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:self.size.width * self.size.height]; 38 | [ASCIIString appendString:[super description]]; 39 | 40 | if (!self) { 41 | [ASCIIString appendString:@"Image is nil!"]; 42 | return ASCIIString; 43 | } else if (asciiDebugType == ASCIIImageTypeBoth || 44 | asciiDebugType == ASCIIImageTypeLogOnly) { 45 | [ASCIIString appendString:@"\n"]; 46 | [ASCIIString appendString:[self convertToASCII]]; 47 | [ASCIIString appendString:@"\n"]; 48 | } 49 | 50 | return (NSString *)ASCIIString; 51 | } 52 | 53 | - (NSString *)debugDescription 54 | { 55 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:self.size.width * self.size.height]; 56 | [ASCIIString appendString:[super description]]; 57 | if (!self) { 58 | [ASCIIString appendString:@"Image is nil!"]; 59 | return ASCIIString; 60 | } else if (asciiDebugType == ASCIIImageTypeBoth || 61 | asciiDebugType == ASCIIImageTypeDebugOnly) { 62 | [ASCIIString appendString:@"\n"]; 63 | [ASCIIString appendString:[self convertToASCII]]; 64 | [ASCIIString appendString:@"\n"]; 65 | } 66 | 67 | return (NSString *)ASCIIString; 68 | } 69 | 70 | //**************************************************************** 71 | #pragma mark - "Private" Methods 72 | //**************************************************************** 73 | 74 | - (NSString *)convertToASCII { 75 | 76 | UIImage *resizedImage = [self resizedImageToFitInSize:CGSizeMake(kMaxWidth, kMaxHeight) scaleIfSmaller:YES]; 77 | CGSize size = resizedImage.size; 78 | int width = size.width; 79 | int height = size.height; 80 | 81 | // the pixels will be painted to this array 82 | uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t)); 83 | 84 | // clear the pixels so any transparency is preserved 85 | memset(pixels, 0, width * height * sizeof(uint32_t)); 86 | 87 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 88 | 89 | // create a context with RGBA pixels 90 | CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8.0f, width * sizeof(uint32_t), colorSpace, 91 | kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); 92 | 93 | // paint the bitmap to our context which will fill in the pixels array 94 | CGContextDrawImage(context, CGRectMake(0, 0, width, height), resizedImage.CGImage); 95 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:width * height + width]; 96 | 97 | for(int y = 0; y < height; y++) { 98 | for(int x = 0; x < width; x++) { 99 | uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x]; 100 | 101 | // convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale 102 | uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; 103 | 104 | NSUInteger position = lroundf((CGFloat)gray * 11.0f/255.0f); 105 | [ASCIIString appendFormat:@"%c", [characterMap characterAtIndex:position]]; 106 | 107 | } 108 | [ASCIIString appendString:@"\n"]; 109 | } 110 | 111 | // we're done with the context, color space, and pixels 112 | CGContextRelease(context); 113 | CGColorSpaceRelease(colorSpace); 114 | free(pixels); 115 | 116 | return [ASCIIString copy]; 117 | } 118 | 119 | -(UIImage*)resizedImageToSize:(CGSize)dstSize 120 | { 121 | CGImageRef imgRef = self.CGImage; 122 | // the below values are regardless of orientation : for UIImages from Camera, width>height (landscape) 123 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which is dependant on the imageOrientation)! 124 | 125 | CGFloat scaleRatio = dstSize.width / srcSize.width; 126 | UIImageOrientation orient = self.imageOrientation; 127 | CGAffineTransform transform = CGAffineTransformIdentity; 128 | switch(orient) { 129 | 130 | case UIImageOrientationUp: //EXIF = 1 131 | transform = CGAffineTransformIdentity; 132 | break; 133 | 134 | case UIImageOrientationUpMirrored: //EXIF = 2 135 | transform = CGAffineTransformMakeTranslation(srcSize.width, 0.0f); 136 | transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 137 | break; 138 | 139 | case UIImageOrientationDown: //EXIF = 3 140 | transform = CGAffineTransformMakeTranslation(srcSize.width, srcSize.height); 141 | transform = CGAffineTransformRotate(transform, M_PI); 142 | break; 143 | 144 | case UIImageOrientationDownMirrored: //EXIF = 4 145 | transform = CGAffineTransformMakeTranslation(0.0, srcSize.height); 146 | transform = CGAffineTransformScale(transform, 1.0f, -1.0f); 147 | break; 148 | 149 | case UIImageOrientationLeftMirrored: //EXIF = 5 150 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 151 | transform = CGAffineTransformMakeTranslation(srcSize.height, srcSize.width); 152 | transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 153 | transform = CGAffineTransformRotate(transform, 3.0f * M_PI_2); 154 | break; 155 | 156 | case UIImageOrientationLeft: //EXIF = 6 157 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 158 | transform = CGAffineTransformMakeTranslation(0.0f, srcSize.width); 159 | transform = CGAffineTransformRotate(transform, 3.0f * M_PI_2); 160 | break; 161 | 162 | case UIImageOrientationRightMirrored: //EXIF = 7 163 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 164 | transform = CGAffineTransformMakeScale(-1.0f, 1.0f); 165 | transform = CGAffineTransformRotate(transform, M_PI_2); 166 | break; 167 | 168 | case UIImageOrientationRight: //EXIF = 8 169 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 170 | transform = CGAffineTransformMakeTranslation(srcSize.height, 0.0f); 171 | transform = CGAffineTransformRotate(transform, M_PI_2); 172 | break; 173 | 174 | default: 175 | [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 176 | 177 | } 178 | 179 | UIGraphicsBeginImageContextWithOptions(dstSize, NO, 0.0f); 180 | 181 | CGContextRef context = UIGraphicsGetCurrentContext(); 182 | 183 | if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 184 | CGContextScaleCTM(context, -scaleRatio, scaleRatio); 185 | CGContextTranslateCTM(context, -srcSize.height, 0.0f); 186 | } else { 187 | CGContextScaleCTM(context, scaleRatio, -scaleRatio); 188 | CGContextTranslateCTM(context, 0.0f, -srcSize.height); 189 | } 190 | 191 | CGContextConcatCTM(context, transform); 192 | 193 | CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0.0f, 0.0f, srcSize.width, srcSize.height), imgRef); 194 | UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext(); 195 | UIGraphicsEndImageContext(); 196 | return resizedImage; 197 | } 198 | 199 | -(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale 200 | { 201 | CGImageRef imgRef = self.CGImage; 202 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); 203 | 204 | UIImageOrientation orient = self.imageOrientation; 205 | switch (orient) { 206 | case UIImageOrientationLeft: 207 | case UIImageOrientationRight: 208 | case UIImageOrientationLeftMirrored: 209 | case UIImageOrientationRightMirrored: 210 | boundingSize = CGSizeMake(boundingSize.height, boundingSize.width); 211 | break; 212 | default: 213 | break; 214 | } 215 | 216 | // Compute the target CGRect in order to keep aspect-ratio 217 | CGSize dstSize; 218 | 219 | if ( !scale && (srcSize.width < boundingSize.width) && (srcSize.height < boundingSize.height) ) { 220 | dstSize = srcSize; 221 | } else { 222 | CGFloat wRatio = boundingSize.width / srcSize.width; 223 | CGFloat hRatio = boundingSize.height / srcSize.height; 224 | 225 | if (wRatio < hRatio) { 226 | dstSize = CGSizeMake(boundingSize.width, floorf(srcSize.height * wRatio)); 227 | } else { 228 | dstSize = CGSizeMake(floorf(srcSize.width * hRatio), boundingSize.height); 229 | } 230 | } 231 | 232 | return [self resizedImageToSize:dstSize]; 233 | } 234 | 235 | @end 236 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/UIImageView+ASCIIConverter.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+ASCIIConverter.h 3 | // ASCII 4 | // 5 | // Created by Derek Selander on 8/26/12. 6 | // Copyright (c) 2012 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIImageView (ASCIIConverter) 12 | - (NSString *)description; 13 | - (NSString *)debugDescription; 14 | @end 15 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/UIImageView+ASCIIConverter.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+ASCIIConverter.m 3 | // ASCII 4 | // 5 | // Created by Derek Selander on 8/26/12. 6 | // Copyright (c) 2012 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import "UIImageView+ASCIIConverter.h" 10 | 11 | typedef enum { 12 | ALPHA = 0, 13 | BLUE = 1, 14 | GREEN = 2, 15 | RED = 3 16 | } PIXELS; 17 | 18 | typedef enum { 19 | ASCIIImageTypeDebugOnly, 20 | ASCIIImageTypeLogOnly, 21 | ASCIIImageTypeBoth, 22 | } ASCIIImageType; 23 | 24 | #define kMaxWidth 75.0f //Adjust for console width 25 | #define kMaxHeight 75.0f //Adjust for console height 26 | //Adjust for printing type. i.e. Log for NSLog(@"%@", imageView), po imageView in debugger 27 | static ASCIIImageType asciiDebugType = ASCIIImageTypeDebugOnly; 28 | static NSString * characterMap = @"#@8%Oo\";,'. "; 29 | 30 | @implementation UIImageView (ASCIIConverter) 31 | 32 | //**************************************************************** 33 | #pragma mark - Public Methods 34 | //**************************************************************** 35 | 36 | - (NSString *)description 37 | { 38 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:self.image.size.width * self.image.size.height]; 39 | [ASCIIString appendString:[super description]]; 40 | 41 | if (!self.image) { 42 | [ASCIIString appendString:@"Image is nil!"]; 43 | return ASCIIString; 44 | } else if (asciiDebugType == ASCIIImageTypeBoth || 45 | asciiDebugType == ASCIIImageTypeLogOnly) { 46 | [ASCIIString appendString:@"\n"]; 47 | [ASCIIString appendString:[self convertToASCII]]; 48 | [ASCIIString appendString:@"\n"]; 49 | } 50 | 51 | return (NSString *)ASCIIString; 52 | } 53 | 54 | - (NSString *)debugDescription 55 | { 56 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:self.image.size.width * self.image.size.height]; 57 | [ASCIIString appendString:[super description]]; 58 | if (!self.image) { 59 | [ASCIIString appendString:@"Image is nil!"]; 60 | return ASCIIString; 61 | } else if (asciiDebugType == ASCIIImageTypeBoth || 62 | asciiDebugType == ASCIIImageTypeDebugOnly) { 63 | [ASCIIString appendString:@"\n"]; 64 | [ASCIIString appendString:[self convertToASCII]]; 65 | [ASCIIString appendString:@"\n"]; 66 | } 67 | 68 | return (NSString *)ASCIIString; 69 | } 70 | 71 | //**************************************************************** 72 | #pragma mark - "Private" Methods 73 | //**************************************************************** 74 | 75 | - (NSString *)convertToASCII { 76 | 77 | UIImage *resizedImage = [self resizedImageToFitInSize:CGSizeMake(kMaxWidth, kMaxHeight) scaleIfSmaller:YES]; 78 | CGSize size = resizedImage.size; 79 | int width = size.width; 80 | int height = size.height; 81 | 82 | // the pixels will be painted to this array 83 | uint32_t *pixels = (uint32_t *) malloc(width * height * sizeof(uint32_t)); 84 | 85 | // clear the pixels so any transparency is preserved 86 | memset(pixels, 0, width * height * sizeof(uint32_t)); 87 | 88 | CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 89 | 90 | // create a context with RGBA pixels 91 | CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8.0f, width * sizeof(uint32_t), colorSpace, 92 | kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedLast); 93 | 94 | // paint the bitmap to our context which will fill in the pixels array 95 | CGContextDrawImage(context, CGRectMake(0, 0, width, height), resizedImage.CGImage); 96 | NSMutableString *ASCIIString = [NSMutableString stringWithCapacity:width * height + width]; 97 | 98 | for(int y = 0; y < height; y++) { 99 | for(int x = 0; x < width; x++) { 100 | uint8_t *rgbaPixel = (uint8_t *) &pixels[y * width + x]; 101 | 102 | // convert to grayscale using recommended method: http://en.wikipedia.org/wiki/Grayscale#Converting_color_to_grayscale 103 | uint32_t gray = 0.3 * rgbaPixel[RED] + 0.59 * rgbaPixel[GREEN] + 0.11 * rgbaPixel[BLUE]; 104 | 105 | NSUInteger position = lroundf((CGFloat)gray * 11.0f/255.0f); 106 | [ASCIIString appendFormat:@"%c", [characterMap characterAtIndex:position]]; 107 | 108 | } 109 | [ASCIIString appendString:@"\n"]; 110 | } 111 | 112 | // we're done with the context, color space, and pixels 113 | CGContextRelease(context); 114 | CGColorSpaceRelease(colorSpace); 115 | free(pixels); 116 | 117 | return [ASCIIString copy]; 118 | } 119 | 120 | -(UIImage*)resizedImageToSize:(CGSize)dstSize 121 | { 122 | CGImageRef imgRef = self.image.CGImage; 123 | // the below values are regardless of orientation : for UIImages from Camera, width>height (landscape) 124 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); // not equivalent to self.size (which is dependant on the imageOrientation)! 125 | 126 | CGFloat scaleRatio = dstSize.width / srcSize.width; 127 | UIImageOrientation orient = self.image.imageOrientation; 128 | CGAffineTransform transform = CGAffineTransformIdentity; 129 | switch(orient) { 130 | 131 | case UIImageOrientationUp: //EXIF = 1 132 | transform = CGAffineTransformIdentity; 133 | break; 134 | 135 | case UIImageOrientationUpMirrored: //EXIF = 2 136 | transform = CGAffineTransformMakeTranslation(srcSize.width, 0.0f); 137 | transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 138 | break; 139 | 140 | case UIImageOrientationDown: //EXIF = 3 141 | transform = CGAffineTransformMakeTranslation(srcSize.width, srcSize.height); 142 | transform = CGAffineTransformRotate(transform, M_PI); 143 | break; 144 | 145 | case UIImageOrientationDownMirrored: //EXIF = 4 146 | transform = CGAffineTransformMakeTranslation(0.0, srcSize.height); 147 | transform = CGAffineTransformScale(transform, 1.0f, -1.0f); 148 | break; 149 | 150 | case UIImageOrientationLeftMirrored: //EXIF = 5 151 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 152 | transform = CGAffineTransformMakeTranslation(srcSize.height, srcSize.width); 153 | transform = CGAffineTransformScale(transform, -1.0f, 1.0f); 154 | transform = CGAffineTransformRotate(transform, 3.0f * M_PI_2); 155 | break; 156 | 157 | case UIImageOrientationLeft: //EXIF = 6 158 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 159 | transform = CGAffineTransformMakeTranslation(0.0f, srcSize.width); 160 | transform = CGAffineTransformRotate(transform, 3.0f * M_PI_2); 161 | break; 162 | 163 | case UIImageOrientationRightMirrored: //EXIF = 7 164 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 165 | transform = CGAffineTransformMakeScale(-1.0f, 1.0f); 166 | transform = CGAffineTransformRotate(transform, M_PI_2); 167 | break; 168 | 169 | case UIImageOrientationRight: //EXIF = 8 170 | dstSize = CGSizeMake(dstSize.height, dstSize.width); 171 | transform = CGAffineTransformMakeTranslation(srcSize.height, 0.0f); 172 | transform = CGAffineTransformRotate(transform, M_PI_2); 173 | break; 174 | 175 | default: 176 | [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 177 | 178 | } 179 | 180 | UIGraphicsBeginImageContextWithOptions(dstSize, NO, 0.0f); 181 | 182 | CGContextRef context = UIGraphicsGetCurrentContext(); 183 | 184 | if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 185 | CGContextScaleCTM(context, -scaleRatio, scaleRatio); 186 | CGContextTranslateCTM(context, -srcSize.height, 0.0f); 187 | } else { 188 | CGContextScaleCTM(context, scaleRatio, -scaleRatio); 189 | CGContextTranslateCTM(context, 0.0f, -srcSize.height); 190 | } 191 | 192 | CGContextConcatCTM(context, transform); 193 | 194 | CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0.0f, 0.0f, srcSize.width, srcSize.height), imgRef); 195 | UIImage* resizedImage = UIGraphicsGetImageFromCurrentImageContext(); 196 | UIGraphicsEndImageContext(); 197 | return resizedImage; 198 | } 199 | 200 | -(UIImage*)resizedImageToFitInSize:(CGSize)boundingSize scaleIfSmaller:(BOOL)scale 201 | { 202 | CGImageRef imgRef = self.image.CGImage; 203 | CGSize srcSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); 204 | 205 | UIImageOrientation orient = self.image.imageOrientation; 206 | switch (orient) { 207 | case UIImageOrientationLeft: 208 | case UIImageOrientationRight: 209 | case UIImageOrientationLeftMirrored: 210 | case UIImageOrientationRightMirrored: 211 | boundingSize = CGSizeMake(boundingSize.height, boundingSize.width); 212 | break; 213 | default: 214 | break; 215 | } 216 | 217 | // Compute the target CGRect in order to keep aspect-ratio 218 | CGSize dstSize; 219 | 220 | if ( !scale && (srcSize.width < boundingSize.width) && (srcSize.height < boundingSize.height) ) { 221 | dstSize = srcSize; 222 | } else { 223 | CGFloat wRatio = boundingSize.width / srcSize.width; 224 | CGFloat hRatio = boundingSize.height / srcSize.height; 225 | 226 | if (wRatio < hRatio) { 227 | dstSize = CGSizeMake(boundingSize.width, floorf(srcSize.height * wRatio)); 228 | } else { 229 | dstSize = CGSizeMake(floorf(srcSize.width * hRatio), boundingSize.height); 230 | } 231 | } 232 | 233 | return [self resizedImageToSize:dstSize]; 234 | } 235 | 236 | @end 237 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/ASCIIArtDebugging/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ASCIIArtDebugging 4 | // 5 | // Created by Derek Selander on 2/2/13. 6 | // Copyright (c) 2013 Derek Selander. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "DSAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([DSAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ASCIIArtDebugging/BigImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekSelander/ASCIIArtDebugging/ce30928c0331e6d17e38df7adb58313a314f8c73/ASCIIArtDebugging/BigImage.jpg -------------------------------------------------------------------------------- /ASCIIArtDebugging/FuturamaMeme.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekSelander/ASCIIArtDebugging/ce30928c0331e6d17e38df7adb58313a314f8c73/ASCIIArtDebugging/FuturamaMeme.jpg -------------------------------------------------------------------------------- /ASCIIArtDebugging/SmallImage.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekSelander/ASCIIArtDebugging/ce30928c0331e6d17e38df7adb58313a314f8c73/ASCIIArtDebugging/SmallImage.jpeg -------------------------------------------------------------------------------- /ASCIIArtDebugging/meme.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekSelander/ASCIIArtDebugging/ce30928c0331e6d17e38df7adb58313a314f8c73/ASCIIArtDebugging/meme.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ASCIIArtDebugging 2 | ================= 3 | 4 | 5 | ASCIIArtDebugging is a fun yet useful way to debug UIImage & UIImageViews in order to see what gets passed around for 6 | the image at runtime. Instead of just looking at the memory address or properties while debugging, ASCIIArtDebugging 7 | takes the image and creates an ASCIIArt image in your console. 8 | 9 | ASCIIArtDebugging can accomidate different Xcode window console sizes as well as different types of image sizes and data types. 10 | 11 | You can adjust the kMaxWidth and kMaxHeight values to accomodate your appropriate screen size. 12 | 13 | ASCIIArtDebugging In Action 14 | =========================== 15 | 16 | In the lldb console:
17 | (lldb) po image 18 | or
19 | (lldb) po imageview 20 | 21 | 22 | ![Alt text](/ScreenShot.png?raw=true "ASCIIArt In Action") 23 | 24 | 25 | Install 26 | ======= 27 | Simply place the category methods in your PCH file and compile your project. Feel free to adjust adjust the screen size in 28 | the .m files. You can also toggle to print out ascii art in debug mode only. i.e. Debug Only will display ascii art when 29 | typing "po imageInstance" but would not display ascii art in NSLog("here is an image %@", imageInstance); 30 | 31 | Licensing 32 | ========= 33 | 34 | The MIT License (MIT) 35 | 36 | Copyright (c) 2013 Selander 37 | 38 | Permission is hereby granted, free of charge, to any person obtaining a copy 39 | of this software and associated documentation files (the "Software"), to deal 40 | in the Software without restriction, including without limitation the rights 41 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 42 | copies of the Software, and to permit persons to whom the Software is 43 | furnished to do so, subject to the following conditions: 44 | 45 | The above copyright notice and this permission notice shall be included in 46 | all copies or substantial portions of the Software. 47 | 48 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 49 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 50 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 51 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 52 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 53 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 54 | THE SOFTWARE. 55 | -------------------------------------------------------------------------------- /ScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DerekSelander/ASCIIArtDebugging/ce30928c0331e6d17e38df7adb58313a314f8c73/ScreenShot.png --------------------------------------------------------------------------------