Search code examples
iosobjective-cuiimagecore-graphicsaffinetransform

iOS: How to diagonally mirror an image using Core Graphics


My aim is, for a given UIImage, to generate another UIImage which is diagonally mirrored version of the original image. I am using Core Graphics to implement this.

My attempt was to generate an affine transform matrix for the diagonal mirror operation as follows:

|0 1 0|
|1 0 0|
|0 0 1|

but the resultant image comes as a rotated image, not diagonally mirrored...

More specifically, here is the code I tried:

+ (UIImage *)mirrorImageDiagonal:(UIImage *)fromImage 
{
    CGContextRef mainViewContentContext = MyCreateBitmapContext(fromImage.size.width, fromImage.size.height);


    CGAffineTransform transform = CGAffineTransformIdentity;
    transform.a = 0;
    transform.b = 1;
    transform.c = 1;
    transform.d = 0;
    transform.tx = 0;
    transform.ty = 0;
    CGContextConcatCTM(mainViewContentContext, transform);

    // draw the image into the bitmap context
    CGContextDrawImage(mainViewContentContext, CGRectMake(0, 0, fromImage.size.width, fromImage.size.height), fromImage.CGImage);

    // create CGImageRef of the main view bitmap content, and then release that bitmap context
    CGImageRef reflectionImage = CGBitmapContextCreateImage(mainViewContentContext);
    CGContextRelease(mainViewContentContext);

    // convert the finished reflection image to a UIImage
    UIImage *theImage = [UIImage imageWithCGImage:reflectionImage];

    // image is retained by the property setting above, so we can release the original
    CGImageRelease(reflectionImage);

    return theImage;
}

Is the problem with the transformation matrix? or with how I am using the Core Graphics?


Solution

  • the matrix you are using will apply a transform about the diagonal of coordinate not about the diagonal of image. (unless the image has a square size in this case they are the same axe).

    the image you get however it seems a rotation but in fact it's a inverted-image;

    + (UIImage *)mirrorImageDiagonal1:(UIImage *)fromImage{
    
            //large square (max(h,w),max(h,w))
            CGSize neededSize = CGSizeMake(fromImage.size.height, fromImage.size.height);//should be max(h,w)
    
            UIGraphicsBeginImageContext(mirrorSize);
            CGContextRef context = UIGraphicsGetCurrentContext();
    
            // Tanslate and scale upside-down to compensate for Quartz's inverted coordinate system
    
            CGContextTranslateCTM(context, 0, fromImage.size.height);
            CGContextScaleCTM(context, 1.0, -1.0);
    
    
            CGAffineTransform transform = CGAffineTransformIdentity;
            transform.a = 0;
            transform.b = 1;
            transform.c = 1;
            transform.d = 0;
            transform.tx = 0;
            transform.ty = 0;
            //transform = CGAffineTransformInvert(transform);
            CGContextConcatCTM(context, transform);
    
            // draw the image into the bitmap context
            CGContextDrawImage(context, CGRectMake(0,0 , fromImage.size.width, fromImage.size.height), fromImage.CGImage);
    
    
    
            // create CGImageRef of the main view bitmap content, and then release that bitmap context
    
            CGImageRef reflectionImage = CGBitmapContextCreateImage(context);
    
            CGContextRelease(context);
    
            // convert the finished reflection image to a UIImage
            UIImage *theImage = [UIImage imageWithCGImage:reflectionImage];
    
            // image is retained by the property setting above, so we can release the original
            CGImageRelease(reflectionImage);
    
            return theImage;
        }