You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无损获取UIImage的水平/垂直镜像?

无损获取镜像图片的解决方案

Hey,我明白你遇到的困扰——用修改UIImageOrientation或者CIImage变换的方法做镜像后,画质莫名下降了对吧?其实问题出在这些方法的底层处理上:要么是orientation的间接转换在某些场景下触发了系统的隐式重绘采样,要么是默认创建的CIContext没有对齐原图的像素格式和缩放比例,导致了不必要的图像损失。

下面给你两种可靠的无损镜像实现方案,都是能完美保留原图分辨率、scale和颜色信息的:

方案一:Core Graphics直接绘制(最推荐)

这个方法直接操作像素缓冲区,完全绕开可能导致损失的中间转换,是最稳妥的方式。可以给UIImage写个分类,方便调用:

#import <UIKit/UIKit.h>

@interface UIImage (Mirror)

// 水平镜像(左右翻转)
- (UIImage *)horizontalMirrorImage;
// 垂直镜像(上下翻转)
- (UIImage *)verticalMirrorImage;

@end

@implementation UIImage (Mirror)

- (UIImage *)horizontalMirrorImage {
    // 用原图的size和scale创建绘图上下文,保证像素密度一致
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 先把坐标系平移到图片右侧,再水平翻转X轴
    CGContextTranslateCTM(context, self.size.width, 0);
    CGContextScaleCTM(context, -1.0, 1.0);
    
    // 直接绘制原图,完全复用原有像素数据
    [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
    
    UIImage *mirroredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return mirroredImage;
}

- (UIImage *)verticalMirrorImage {
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 平移坐标系到图片底部,再垂直翻转Y轴
    CGContextTranslateCTM(context, 0, self.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    
    [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
    
    UIImage *mirroredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return mirroredImage;
}

@end

为什么这个方案无损?

  • 用UIGraphicsBeginImageContextWithOptions时传入了原图的scale,保证输出图片的像素密度和原图完全一致;
  • 直接通过坐标系变换绘制,没有经过CIImage转换或orientation触发的隐式重绘;
  • 绘制过程完全复用原图的像素数据,不会改变颜色空间或进行额外的采样处理。

方案二:优化后的CIImage方案(如果你偏好Core Image)

如果你坚持想用CIImage的方式,那一定要给CIContext配置和原图匹配的参数,避免默认设置导致的颜色空间转换或采样损失:

- (UIImage*)getHoriMirror:(UIImage*)img {
    CIImage* cii = [CIImage imageWithCGImage:img.CGImage];
    // 水平镜像用CGAffineTransformMakeScale(-1, 1),垂直镜像用(1, -1)
    cii = [cii imageByApplyingTransform:CGAffineTransformMakeScale(-1, 1)];
    
    // 获取原图的颜色空间,保证CIContext和原图对齐
    CGColorSpaceRef colorSpace = CGImageGetColorSpace(img.CGImage);
    CIContext *context = [CIContext contextWithCGColorSpace:colorSpace
                                                     options:@{
                                                               kCIContextOutputColorSpace: colorSpace,
                                                               kCIContextWorkingColorSpace: colorSpace,
                                                               kCIContextUseSoftwareRenderer: @NO // 优先用硬件加速
                                                               }];
    CGImageRef cgImage = [context createCGImage:cii fromRect:[cii extent]];
    // 一定要保留原图的scale和orientation
    UIImage* uiImage = [UIImage imageWithCGImage:cgImage scale:img.scale orientation:img.imageOrientation];
    CGImageRelease(cgImage);
    return uiImage;
}

这样修改后,CIImage的处理就不会再因为颜色空间不匹配或者scale丢失导致画质下降了。

内容的提问来源于stack exchange,提问作者Sudhanshu Monga

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 06:53:24