Отразить UIImage вдоль любой оси - PullRequest
4 голосов
/ 24 июня 2011

Я пытаюсь создать метод, который переворачивает UIImage вдоль оси X, оси Y или обоих.Я продолжаю приближаться, но мои знания о трансформации недостаточно хороши, чтобы пройти весь путь.Вот код, который у меня есть:

- (UIImage *)flippedImageByAxis:(MVImageFlip)axis{
     UIGraphicsBeginImageContext(self.size);
     CGContextRef context = UIGraphicsGetCurrentContext();
     CGAffineTransform verticalFlip = CGAffineTransformMake(1, 0, 0, -1, 0, self.size.height);
     CGAffineTransform horizFlip = CGAffineTransformMake(-1.0, 0.0, 0.0, 1.0, self.size.width, 0.0);

     if(axis == MVImageFlipXAxis || axis == MVImageFlipXAxisAndYAxis)
         CGContextConcatCTM(context, horizFlip);
     if(axis == MVImageFlipYAxis || axis == MVImageFlipXAxisAndYAxis)
         CGContextConcatCTM(context, verticalFlip);

     CGContextDrawImage(context, CGRectMake(0.0, 0.0, self.size.width, self.size.height), [self CGImage]);

     UIImage *flipedImage = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();

     return flipedImage;
 }

Это переворачивает изображение, но не правильно.Изображение, перевернутое по оси Y, не переворачивается вообще, изображение, перевернутое по X, выглядит так, как должно выглядеть изображение XY, а изображение по XY выглядит так, как должно выглядеть изображение Y.Комбинирование преобразований и их правильная работа причиняют мне боль.

Перечисление MVImageFlip - это всего лишь три, которые вы видите в коде.Ничего особенного.

Ответы [ 5 ]

24 голосов
/ 26 июня 2011

Я наконец смог понять это.Вот код, который работает для всех, кому это может понадобиться.

- (UIImage *)flippedImageByAxis:(MVImageFlip)axis{
    UIGraphicsBeginImageContext(self.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    if(axis == MVImageFlipXAxis){
        // Do nothing, X is flipped normally in a Core Graphics Context
    } else if(axis == MVImageFlipYAxis){
        // fix X axis
        CGContextTranslateCTM(context, 0, self.size.height);
        CGContextScaleCTM(context, 1.0f, -1.0f);

        // then flip Y axis
        CGContextTranslateCTM(context, self.size.width, 0);
        CGContextScaleCTM(context, -1.0f, 1.0f);
    } else if(axis == MVImageFlipXAxisAndYAxis){
        // just flip Y
        CGContextTranslateCTM(context, self.size.width, 0);
        CGContextScaleCTM(context, -1.0f, 1.0f);
    }

    CGContextDrawImage(context, CGRectMake(0.0, 0.0, self.size.width, self.size.height), [self CGImage]);

    UIImage *flipedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return flipedImage;
}
9 голосов
/ 24 июня 2011

Попробуйте следующее:

UIImage* myimage = [UIImage imageNamed: @"myimage.png"];
myimage = [UIImage imageWithCGImage: myimage.CGImage scale: 1.0f orientation: UIImageOrientationUpMirrored];
6 голосов
/ 14 декабря 2013

Если вы намереваетесь просто отобразить изображение, а не сохранить его, вы, вероятно, не хотите создавать второй CGContext. Гораздо эффективнее просто использовать уже загруженный CGImage в UIImage и изменить ориентацию следующим образом:

- (UIImage *)flippedImageByFlippingAlongXAxis:(BOOL)flipOnX andAlongYAxis:(BOOL)flipOnY
{
    UIImageOrientation currentOrientation = self.imageOrientation;
    UIImageOrientation newOrientation = currentOrientation;

    if (flipOnX == YES) {
        switch (newOrientation) {
            case UIImageOrientationUp:
                newOrientation = UIImageOrientationUpMirrored;
                break;
            case UIImageOrientationDown:
                newOrientation = UIImageOrientationMirrored;
                break;
            case UIImageOrientationUpMirrored:
                newOrientation = UIImageOrientationUp;
                break;
            case UIImageOrientationDownMirrored:
                newOrientation = UIImageOrientationDown;
                break;
            case UIImageOrientationLeft:
                newOrientation = UIImageOrientationLeftMirrored;
                break;
            case UIImageOrientationRight:
                newOrientation = UIImageOrientationRightMirrored;
                break;
            case UIImageOrientationLeftMirrored:
                newOrientation = UIImageOrientationLeft;
                break;
            case UIImageOrientationRightMirrored:
                newOrientation = UIImageOrientationRight;
                break;
        }
    }

    if (flipOnY == YES) {
        switch (newOrientation) {
            case UIImageOrientationUp:
                newOrientation = UIImageOrientationDownMirrored;
                break;
            case UIImageOrientationDown:
                newOrientation = UIImageOrientationUpMirrored;
                break;
            case UIImageOrientationUpMirrored:
                newOrientation = UIImageOrientationDown;
                break;
            case UIImageOrientationDownMirrored:
                newOrientation = UIImageOrientationUp;
                break;
            case UIImageOrientationLeft:
                newOrientation = UIImageOrientationRightMirrored;
                break;
            case UIImageOrientationRight:
                newOrientation = UIImageOrientationLeftMirrored;
                break;
            case UIImageOrientationLeftMirrored:
                newOrientation = UIImageOrientationRight;
                break;
            case UIImageOrientationRightMirrored:
                newOrientation = UIImageOrientationLeft;
                break;
        }
    }

    return [UIImage imageWithCGImage:self.CGImage scale:self.scale orientation:newOrientation];
}

Когда вы запускаете новый CGContext и делаете переворот с использованием CGContextDrawImage, вы выделяете другой блок памяти для хранения тех же байтов в другом порядке. Изменяя ориентацию UIImage, вы можете избежать другого выделения. Используются одни и те же данные изображения, только нарисованные в другой ориентации.

2 голосов
/ 17 июня 2015

Это просто слегка исправленная и «обновленная до Swift» версия старого ответа от @ultramiraculous.На всякий случай это кому-нибудь поможет.

Вертикальный переворот (отражение по оси x):

func flipV(im:UIImage)->UIImage {
    var newOrient:UIImageOrientation
    switch im.imageOrientation {
    case .Up:
        newOrient = .DownMirrored
    case .UpMirrored:
        newOrient = .Down
    case .Down:
        newOrient = .UpMirrored
    case .DownMirrored:
        newOrient = .Up
    case .Left:
        newOrient = .LeftMirrored
    case .LeftMirrored:
        newOrient = .Left
    case .Right:
        newOrient = .RightMirrored
    case .RightMirrored:
        newOrient = .Right
    }
    return UIImage(CGImage: im.CGImage, scale: im.scale, orientation: newOrient)
}

Горизонтальный переворот (отражение по оси y)

func flipH(im:UIImage)->UIImage {
    var newOrient:UIImageOrientation
    switch im.imageOrientation {
    case .Up:
        newOrient = .UpMirrored
    case .UpMirrored:
        newOrient = .Up
    case .Down:
        newOrient = .DownMirrored
    case .DownMirrored:
        newOrient = .Down
    case .Left:
        newOrient = .RightMirrored
    case .LeftMirrored:
        newOrient = .Right
    case .Right:
        newOrient = .LeftMirrored
    case .RightMirrored:
        newOrient = .Left
    }
    return UIImage(CGImage: im.CGImage, scale: im.scale, orientation: newOrient)
}
0 голосов
/ 14 января 2017

Swift 3 версия:

func flipV(im:UIImage)->UIImage {
        var newOrient:UIImageOrientation
        switch im.imageOrientation {
        case .up:
            newOrient = .downMirrored
        case .upMirrored:
            newOrient = .down
        case .down:
            newOrient = .upMirrored
        case .downMirrored:
            newOrient = .up
        case .left:
            newOrient = .leftMirrored
        case .leftMirrored:
            newOrient = .left
        case .right:
            newOrient = .rightMirrored
        case .rightMirrored:
            newOrient = .right
        }
        return UIImage(cgImage: im.cgImage!, scale: im.scale, orientation: newOrient)
    }

    func flipH(im:UIImage)->UIImage {
        var newOrient:UIImageOrientation
        switch im.imageOrientation {
        case .up:
            newOrient = .upMirrored
        case .upMirrored:
            newOrient = .up
        case .down:
            newOrient = .downMirrored
        case .downMirrored:
            newOrient = .down
        case .left:
            newOrient = .rightMirrored
        case .leftMirrored:
            newOrient = .right
        case .right:
            newOrient = .leftMirrored
        case .rightMirrored:
            newOrient = .left
        }
        return UIImage(cgImage: im.cgImage!, scale: im.scale, orientation: newOrient)
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...