你的位置:首页 > 软件开发 > 操作系统 > iOS 实现图片自定义变换

iOS 实现图片自定义变换

发布时间:2017-11-10 19:00:32
先看效果看加载了一张image,根据四个顶点任意变换。 知识点:1.BitmapContext 2.矩阵变换 一.什么是BitmapContext官方解释:The number of components for each pixel in a bitmap ...

iOS 实现图片自定义变换

先看效果看iOS 实现图片自定义变换加载了一张image,根据四个顶点任意变换。 知识点:1.BitmapContext  2.矩阵变换  一.什么是BitmapContext官方解释:The number of components for each pixel in a bitmap graphics context is specified by a color space, defined by a CGColorSpaceRef. The bitmap graphics context specifies whether the bitmap should contain an alpha channel, and how the bitmap is generated.通俗来讲:首先,我们根据图片创建一个BitmapContext,把一张图片绘制到这个BitmapContext上。这时你可以把图片看成是由很多个彩色的点组成的。iOS 实现图片自定义变换图片局部放大后就形成了一个表格。每个单元代表一个像素点其中包含了4个元素:alpha(透明度)红 绿 蓝iOS 实现图片自定义变换                    每个像素点包含的信息 1.创建
CGContextRef contexRef = CGBitmapContextCreate(void *data, size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow, CGColorSpaceRef space, uint32_t bitmapInfo);
 data: 创建BitmapContext所需的内存空间,由malloc创建 width: 图片的宽度 height: 图片的高度 bitsPerComponent: data中的每个数据所占的字节数 bytesPerRow: 图片每行的位数 = 图片列数*4(因为每个点有4个通道) space: 颜**间 bitmapInfo: bitmap类型,一般选择PremultipliedFirst(ARGB) 2.读取图片中的所有像素点数据
unsigned char* needData = malloc(需要多大);needData = CGBitmapContextGetData(contexRef);
 3.读取某个点的内容   
 int alpha = needData[4*n]; int red = needData[4*n+1]; int green = needData[4*n+2]; int blue = needData[4*n+3];
一个点由4个信息表示 4.修改某个点的内容
 newData[4*n ] = alpha; newData[4*n + 1] = red; newData[4*n + 2] = green; newData[4*n + 3] = blue; 
5.把data数据从新编程UIImage
CGImageRef cgImage = CGBitmapContextCreateImage(newContext);_imageView.image = [UIImage imageWithCGImage:cgImage ];
 有个了几个函数,接下来就需要你来指定一套规则,获取到的所有像素点,然后从组元素生成一张新的图片。 而这套规则就是下面对应的矩阵变换  二.矩阵变换 注:这个部分原理居多,若有不是可以直接跳过copy代码,不影响你功能的实现1.什么是矩阵若用一个行向量[X1 X2 ….Xn]表示n维空间中的一个点的坐标,那么n维空间中m个点坐标就可以表示为一个向量集合,这个集合就是一个矩阵。iOS 实现图片自定义变换也就是说我们二维图片中所有的(x,y)坐标的所有点组成的一个集合就是一个矩阵. iOS 实现图片自定义变换所有的图形点由老的x y坐标变成了新的x` y`坐标 3.常见的图形变换基本的二维变换可包括旋转、缩放、扭曲,和平移四种,        iOS 实现图片自定义变换    iOS 实现图片自定义变换    iOS 实现图片自定义变换而这些几何运算则可以转换为一些基本的矩阵运算:    iOS 实现图片自定义变换这几个变换都是线性的,但平移运算不是线性的,不能通过2*2矩阵运算完成。若要将点 (2, 1)在 x 方向将其平移 3 个单位,在 y 方向将其平移 4 个单位。 可通过先使用矩阵乘法再使用矩阵加法来完成此操作。    iOS 实现图片自定义变换综合这几种基本运算,数学家们将其统一为一个3*3矩阵,存储形式如下:    iOS 实现图片自定义变换由于表示仿射变换的矩阵的第三列总是(0,0,1),在存储矩阵的时候,大多只存成一个2*3的数组。  三.从由4个新顶点组成的图片中找到对应图形变换的规律 方法1.通过矩阵乘法计算iOS 实现图片自定义变换原始坐标和变换好后的四个顶点坐标我们都是已知的,可以通过已知数据建立一个4元一次方程式,得出a b c d四个位置数然后计算出新的图形坐标。此方式适用于做数学应用题。 方法2.通过x y的线性变换找出规律我们之前拿到的图片都是很规规矩矩的,是一个矩形。加入得到x相对于自己图形空间的坐标的话,这个x的坐标就是 (7/11 * 图片宽度,4/8 *图片高度)iOS 实现图片自定义变换比如我要把x点移动到b点怎么实现呢? iOS 实现图片自定义变换 我们可以把上面的直角坐标系想象成一辆公交车,所有的点都坐在公交车里面,我们在车里没有动,然后公交车到达目的地后,我们相对于城市而言已经走了很远很远了。iOS 实现图片自定义变换就像这样,x点是不是就移动到b点了。 重点:所以计算的思路就是,通过老的直角坐标系的规律获取到每一个点的位置,再找出新的坐标系的规律,把点移动上去,就完成了第一张图片所达到的效果了 下面开始找规律假如新的图片变成了这样iOS 实现图片自定义变换由于4个顶点已知,那么这4条边有多长,每个边上面的点的具体坐标我们就可以确认下来。iOS 实现图片自定义变换iOS 实现图片自定义变换由上下两条边线确认两个顶点,我们就可以确认某一个X坐标上面y的线性变化规律。 比如以前图片位于x方面1/4位置的坐标点y方向线性变换在新图中的线性变换就变成了左图y’.    X坐标固定,这时候我们只需要传入以前坐标中的y值,就能得到相对于自己宽度1/4出的新图中所有的坐标点。iOS 实现图片自定义变换同理可得,以前2/4 3/4等等所有顶点方向的y线性变换规律我们都可以得到。然后我们要做的就是通过循环遍历出所有向下顶点然后得到第n个位置处的所有y方向的点,从而得出所有的坐标。然后这一组坐标的就组成了新的图片。 最后附上关键代码//数组包含了一次是 左上 右上 右下 左下  4个点位置不同,图片显示的就不同
 1 -(void)changeImageByPoints:(NSArray *)pointArray{ 2  UIImage * image = _image; //全局需要变换的图片 3  float width = CGImageGetWidth(image.CGImage); 4  float height = CGImageGetHeight(image.CGImage); 5   6  CGPoint p0 = [pointArray[0]CGPointValue]; 7  CGPoint p1 = [pointArray[1]CGPointValue]; 8  CGPoint p2 = [pointArray[2]CGPointValue]; 9  CGPoint p3 = [pointArray[3]CGPointValue];10  11  //痛觉相对于父视图的绝对4个顶点计算出新的宽度和高度12  float minLeft = MIN(MIN(p0.x, p1.x), MIN(p2.x, p3.x));13  float minTop = MIN(MIN(p0.y, p1.y), MIN(p2.y, p3.y));14  float shapW = KINT((MAX(MAX(p0.x, p1.x), MAX(p2.x, p3.x)) - minLeft));15  float shapH = KINT((MAX(MAX(p0.y, p1.y), MAX(p2.y, p3.y)) - minTop));16  17  //change point relative to image not superview18  p0.x = p0.x - minLeft;19  p1.x = p1.x - minLeft;20  p2.x = p2.x - minLeft;21  p3.x = p3.x - minLeft;22  p0.y = p0.y - minTop;23  p1.y = p1.y - minTop;24  p2.y = p2.y - minTop;25  p3.y = p3.y - minTop; 26  27  //创建一个bitmapcontext28  if (!_first) {29   needData = malloc(KINT(width)* KINT(height) * 4);30   CGContextRef imageContext = CGBitmapContextCreate(needData, width, height, 8, width * 4, CGImageGetColorSpace(image.CGImage), CGImageGetAlphaInfo(image.CGImage));31   CGContextDrawImage(imageContext, CGRectMake(0, 0, width, height), image.CGImage);32   data = malloc(KINT(width) * KINT(height) * 4);33   data = CGBitmapContextGetData(imageContext);34   _first = YES;35  } 36  37  //初始化新的图片需要的data38  unsigned char* shapeData = malloc(shapW * shapH * 4);39  for (int i = 0; i < shapH -1; i ++) {40   for (int j = 0; j < shapW -1; j++) {41    int offset = (i * shapW + j) * 4;42    shapeData[offset] = 255;43    shapeData[offset + 1] = 255;44    shapeData[offset + 2] = 255;45    shapeData[offset + 3] = 255;46   }47  }48 49  //给data添加对应的像素值50  for (int i = 0; i < height -1; i++) {51   for (int j = 0; j < width -1; j++) {52    CGPoint originPoint = CGPointMake(j, i);53    int originOffset = (i * width + j) * 4;54    // 计算原图每个点在新图中的位置55    float xFunc = (float)originPoint.x / (float)width;56    float yFunc = (float)originPoint.y / (float)height;57     58    float delx = (p1.x - p0.x) * xFunc;59    float dely = (p1.y - p0.y) * xFunc;60    CGPoint topPoint = CGPointMake(p0.x + delx, p0.y + dely);61    62    delx = (p2.x - p3.x) * xFunc;63    dely = (p2.y - p3.y) * xFunc;64    CGPoint bottomPoint = CGPointMake(p3.x + delx, p3.y + dely);65    66    delx = (bottomPoint.x - topPoint.x) * yFunc;67    dely = (bottomPoint.y - topPoint.y) * yFunc;68    69    CGPoint newPoint = CGPointMake(topPoint.x + delx, topPoint.y + dely);70    71    int newOffset = ((KINT(newPoint.y) * shapW + KINT(newPoint.x))) * 4;72    73    //give shapeView new value74    shapeData[newOffset] = data[originOffset];75    shapeData[newOffset + 1] = data[originOffset + 1];76    shapeData[newOffset + 2] = data[originOffset + 2];77    shapeData[newOffset + 3] = data[originOffset + 3];78    79   }80  }81  //创建新图片82  CGContextRef newContext = CGBitmapContextCreate(shapeData, shapW, shapH, 8, shapW * 4, CGImageGetColorSpace(image.CGImage), CGImageGetAlphaInfo(image.CGImage));83  84  CGImageRef cgImage = CGBitmapContextCreateImage(newContext);85  _imageView.image = [UIImage imageWithCGImage:cgImage ]; //这个_imageView就是贴上viewcontroller上面的UIImageview86  _imageView.frame = CGRectMake(minLeft, minTop, shapW, shapH);87  CGContextRelease(newContext);88  CGImageRelease(cgImage);89  free(shapeData);90 }

 

  

原标题:iOS 实现图片自定义变换

关键词:IOS

IOS
*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。