0

I scoured SO and some web tutorials to get this IBAction together that edits the pixels of an UIImage. The edit it supposed to make the photo greyscale, but it also rotates the image too, and I can't figure out why. Can anyone else spot the reason? Thanks!

- (IBAction)grayscale:(id)sender {
    CGContextRef ctx;
    CGImageRef imageRef = [self.workingImage CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    _text1.text = [NSString stringWithFormat: @"%d", width];
    _text2.text = [NSString stringWithFormat: @"%d", height];
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    unsigned char *rawData = malloc(height * width * 4);
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                                                 bitsPerComponent, bytesPerRow, colorSpace,
                                                 kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);


    int byteIndex = 0;
    for (int ii = 0 ; ii < width * height ; ++ii)
    {
        int outputColor = (rawData[byteIndex] + rawData[byteIndex+1] +
                           rawData[byteIndex+2]) / 3;

        rawData[byteIndex] = (char) (outputColor);
        rawData[byteIndex+1] = (char) (outputColor);
        rawData[byteIndex+2] = (char) (outputColor);

        byteIndex += 4;
    }


    ctx = CGBitmapContextCreate(rawData,
                                CGImageGetWidth( imageRef ),
                                CGImageGetHeight( imageRef ),
                                8,
                                CGImageGetBytesPerRow( imageRef ),
                                CGImageGetColorSpace( imageRef ),
                                kCGImageAlphaPremultipliedLast );

    imageRef = CGBitmapContextCreateImage (ctx);
    UIImage* rawImage = [UIImage imageWithCGImage:imageRef];

    CGContextRelease(ctx);  

    self.workingImage = rawImage;  
    [_theImage setImage:_workingImage];
    free(rawData);
}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
jake9115
  • 3,964
  • 12
  • 49
  • 78
  • check your image orientation: UIImageOrientation orient = image.imageOrientation; If it is not 1 you might want to rotate it first. – Thorsten Feb 20 '14 at 08:03
  • Thanks for the advice... orient = 1! Can you please tell me how to rotate it? – jake9115 Feb 20 '14 at 15:25
  • I tried just orienting the UIImageView using `imageView.transform = CGAffineTransformMakeRotation(3.14/2); `, and this shows the picture in the correct orientation, but my picture is now squished to landscape instead of its original portrait! – jake9115 Feb 20 '14 at 15:33

1 Answers1

0

That's how I "fix" image orientation:

- (UIImage*) fixImageOrientation:(UIImage *)image {

    UIImageOrientation orient = image.imageOrientation;
    CGImageRef imgRef = image.CGImage;

    CGFloat aWidth = CGImageGetWidth(imgRef);;
    CGFloat aHeight = CGImageGetHeight(imgRef);

    CGAffineTransform transform = CGAffineTransformIdentity;
    CGRect bounds = CGRectMake(0, 0, aWidth, aHeight);

    CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef));
    CGFloat boundHeight;

    switch(orient)
    {

        case UIImageOrientationUp: //EXIF = 1
            transform = CGAffineTransformIdentity;
            break;

        case UIImageOrientationUpMirrored: //EXIF = 2
            transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            break;

        case UIImageOrientationDown: //EXIF = 3
            transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;

        case UIImageOrientationDownMirrored: //EXIF = 4
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.height);
            transform = CGAffineTransformScale(transform, 1.0, -1.0);
            break;

        case UIImageOrientationLeftMirrored: //EXIF = 5
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width);
            transform = CGAffineTransformScale(transform, -1.0, 1.0);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationLeft: //EXIF = 6
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(0.0, imageSize.width);
            transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0);
            break;

        case UIImageOrientationRightMirrored: //EXIF = 7
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeScale(-1.0, 1.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        case UIImageOrientationRight: //EXIF = 8
            boundHeight = bounds.size.height;
            bounds.size.height = bounds.size.width;
            bounds.size.width = boundHeight;
            transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0);
            transform = CGAffineTransformRotate(transform, M_PI / 2.0);
            break;

        default:
            NSLog(@"Invalid image orientation");

    }

    UIGraphicsBeginImageContext(bounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft)
    {
        CGContextTranslateCTM(context, -aHeight, 0);
    }
    else
    {
        CGContextTranslateCTM(context, 0, -aHeight);
    }

    CGContextConcatCTM(context, transform);

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, aWidth, aHeight), imgRef);
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

HTH

Thorsten
  • 3,102
  • 14
  • 14
  • P.S.: and you are aware that there are easier methods to create a grayscale image than looping through pixels? http://stackoverflow.com/questions/11403939/making-a-uiimageview-grey – Thorsten Feb 20 '14 at 19:35
  • Thanks for your answer! Yes, I am definitely aware, this is just a proof of concept so that I am free to apply other transformative algorithms to the pixels. – jake9115 Feb 20 '14 at 21:32