把一张图纸绘制到那么些BitmapContext上,通俗来讲

先看作用看

iOS 完结图片自定义转变,ios图片自定义转变

先看功能看
图片 1
加载了一张image,依照三个终端任性别变化换。   知识点:壹.BitmapContext
 二.矩阵转换     一.什么是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 阿尔法 channel, and how
the bitmap is generated. 通俗来讲:
首先,大家依据图片创立3个BitmapContext,把一张图纸绘制到那几个BitmapContext上。那时你能够把图纸作为是由众多个有滋有味的点构成的。
图片 2
图片部分放大后就产生了二个报表。每一个单晋朝表三个像素点其中包罗了多少个要素:阿尔法(光滑度)红
绿 蓝
图片 3
                    各个像素点包括的新闻   一.创立

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: 图片每行的位数 =
图片列数*四(因为各种点有多少个通道)  space: 颜色区间  bitmapInfo:
bitmap类型,一般选拔PremultipliedFirst(A奇骏GB)  
二.读取图片中的全体像素点数据

unsigned char* needData = malloc(需要多大);
needData = CGBitmapContextGetData(contexRef);

  三.读取某些点的始末    

  int alpha = needData[4*n];
  int red   = needData[4*n+1];
  int green = needData[4*n+2];
  int blue  = needData[4*n+3];

一个点由多少个消息表示   肆.修改某些点的始末

  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 ];

 
有个了多少个函数,接下去就供给您来钦命1套规则,获取到的有着像素点,然后从组元素生成一张新的图片。
而这套规则就是底下对应的矩阵转变     贰.矩阵变换注:那些片段原理居多,若有不是足以直接跳过copy代码,不影响你成效的兑现
一.如何是矩阵 若用2个行向量[X1 X2
….Xn]代表n维空间中的三个点的坐标,那么n维空间中m个点坐标就足以代表为四个向量会集,这一个集结正是八个矩阵。
图片 4

 

也正是说大家2维图片中全体的(x,y)坐标的全体点组成的多个汇集便是二个矩阵.
 
图片 5
           图片和中间的一小点   二.图形调换大家对图像的大规模操作实际正是对图纸举行考核评议、旋转、缩放等矩阵调换,实质上正是改动了逐一点的坐标。
图片 6

抱有的图形点由老的x y坐标产生了新的x` y`坐标

  三.大规模的图片转变 基本的2维调换可回顾旋转、缩放、扭曲,和平移各类,
        图片 7    图片 8    图片 9    图片 10
而这一个几何运算则足以转移为一些基本的矩阵运算:
    图片 11
那多少个转移都是线性的,但平移运算不是线性的,不能够通过二*二矩阵运算完结。若要将点
(二, 壹)在 x 方向将其移动 三 个单位,在 y 方向将其平移 陆个单位。 可透过先选取矩阵乘法再选拔矩阵加法来产生此操作。
    图片 12
综合那两种为主运算,化学家们将其联合为二个三*3矩阵,存款和储蓄情势如下:
    图片 13
由于表示仿射调换的矩阵的第贰列总是(0,0,1),在存款和储蓄矩阵的时候,大八只存成三个2*3的数组。
    三.从由八个新顶点组成的图样中找到呼应图形转换的原理  
方法一.通过矩阵乘法总结
图片 14
原始坐标和转移好后的多少个终端坐标我们都以已知的,能够通过已知多少建立3个四元3遍方程式,得出a
b c d四个地点数然后总结出新的图片坐标。此措施适用于做数学应用题。  
方法二.因而x y的线性别变化换找寻规律
大家事先获得的图形都以很老老实实的,是贰个矩形。插足获得x相对于自身图形空间的坐标的话,那些x的坐标就是(7/1一 * 图片宽度,四分之二 *图表中度)
图片 15
要是1个图形变化了,那么那一个j
和i向量就不在是先前相互垂直90度了,然后中间有着的点坐标恐怕就位移了。
图片 16
例如作者要把x点移动到b点怎么得以落成啊?  
图片 17  
我们能够把地方的直角坐标系想象成壹辆公共交通车,全部的点都坐在公交车里面,大家在车里没有动,然后公共交通车到达目标地后,大家相对于城市来说已经走了很远很远了。
图片 18
就如那样,x点是还是不是就活动到b点了。  
注重:所以总结的思路正是,通过老的直角坐标系的法则获取到每3个点的地点,再找寻新的坐标系的原理,把点运动上去,就做到了第3张图纸所实现的成效了
  上边开始找规律 借使新的图形变成了这么
图片 19

 

由于四个极点已知,那么那4条边有多少长度,每一个边上边包车型客车点的切切实实坐标我们就能够料定下来。
图片 20图片 21

 

由上下两条边线确认多少个顶峰,大家就足以料定某叁个X坐标下边y的线性别变化化规律。
比方从前图片位于x方面四分一岗位的坐标点y方向线性别变化换在新图中的线性别变化换就改为了左图y’.
 
 X坐标固定,那时候大家只需求传入从前坐标中的y值,就能获得相对于本人宽度25%出的新图中享有的坐标点。
图片 22
不问可见,从前2/肆 肆分三之类全数终端方向的y线性别变化换规律大家都能够获得。
然后大家要做的正是因而巡回遍历出装有向下顶点然后获得第n个职位处的全体y方向的点,从而得出全部的坐标。然后这一组坐标的就结成了新的图片。
  最终附上关键代码 //数组包蕴了三次是 左上 右上 右下 左下
 三个点地点区别,图片突显的就分歧

 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 superview
18     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     //创建一个bitmapcontext
28     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     //初始化新的图片需要的data
38     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 value
74             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上面的UIImageview
86     _imageView.frame = CGRectMake(minLeft, minTop, shapW, shapH);
87     CGContextRelease(newContext);
88     CGImageRelease(cgImage);
89     free(shapeData);
90 }

 

http://www.bkjia.com/IOSjc/1232456.htmlwww.bkjia.comtruehttp://www.bkjia.com/IOSjc/1232456.htmlTechArticleiOS 达成图片自定义转变,ios图片自定义变换先看效果看
加载了一张image,依照多个终端任性转换。知识点:一.BitmapContext
二.矩阵转换 壹.什么…

图片 23

加载了一张image,依据两个终端放肆转换。

 

知识点:一.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上。那时你能够把图片作为是由众多个五光十色的点组成的。

图片 24

图形部分放大后就变成了三个表格。每一个单南梁表3个像素点在那之中包蕴了6个成分:阿尔法(光滑度)红
绿 蓝

图片 25

                    每一个像素点包罗的新闻

 

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: 图片每行的位数 = 图片列数*四(因为各个点有伍个通道)

 space: 颜色区间

 bitmapInfo: bitmap类型,一般选拔PremultipliedFirst(AHavalGB)

 

贰.读取图片中的全部像素点数据

unsigned char* needData = malloc(需要多大);
needData = CGBitmapContextGetData(contexRef);

 

三.读取有个别点的内容  

 

  int alpha = needData[4*n];
  int red   = needData[4*n+1];
  int green = needData[4*n+2];
  int blue  = needData[4*n+3];

3个点由5个音讯表示

 

四.修改有些点的剧情

  newData[4*n    ] = alpha;
  newData[4*n + 1] = red;
  newData[4*n + 2] = green;
  newData[4*n + 3] = blue;

伍.把data数据从新编制程序UIImage

CGImageRef cgImage = CGBitmapContextCreateImage(newContext);
_imageView.image = [UIImage imageWithCGImage:cgImage ];

 

有个了多少个函数,接下去就要求您来钦赐1套规则,获取到的富有像素点,然后从组成分生成一张新的图片。
而那套规则便是下面对应的矩阵调换

 

 

二.矩阵转变注:那个片段原理居多,若有不是足以间接跳过copy代码,不影响你功能的兑现

1.怎么着是矩阵

若用多个行向量[X1 X2
….Xn]代表n维空间中的二个点的坐标,那么n维空间中m个点坐标就能够代表为三个向量集结,这么些会集正是3个矩阵。

图片 26

 

约等于说大家二维图片中享有的(x,y)坐标的全数点组成的一个集结正是一个矩阵.

 

图片 27

           图片和在那之中的少数点

 

二.图形调换

大家对图像的宽泛操作实际正是对图纸举行判断、旋转、缩放等矩阵转换,实质上便是改造了逐条点的坐标。

图片 28

富有的图形点由老的x y坐标形成了新的x` y`坐标

 

三.宽广的图形调换

主导的2维转换可归纳旋转、缩放、扭曲,和平移两种,

        图片 29    图片 30    图片 31    图片 32

而那一个几何运算则能够调换为一些骨干的矩阵运算:

    图片 33

那多少个转移都以线性的,但平移运算不是线性的,不能够因而2*二矩阵运算落成。若要将点
(二, 1)在 x 方向将其活动 3 个单位,在 y 方向将其平移 伍个单位。 可经过先利用矩阵乘法再利用矩阵加法来成功此操作。

    图片 34

汇总那两种为主运算,地文学家们将其统壹为三个三*3矩阵,存款和储蓄方式如下:

    图片 35

是因为表示仿射转变的矩阵的第三列总是(0,0,1),在积攒矩阵的时候,大四只存成三个2*3的数组。

 

 

3.从由5个新顶点组成的图形中找到呼应图形转换的法则

 

措施壹.由此矩阵乘法总计

图片 36

原有坐标和转换好后的八个顶峰坐标大家都以已知的,能够通过已知多少建立1个肆元二遍方程式,得出a
b c d多个岗位数然后总计出新的图片坐标。此格局适用于做数学应用题。

 

主意二.透过x y的线性别变化换搜索规律

我们此前获得的图片都以很老老实实的,是三个矩形。加入得到x相对于自身图形空间的坐标的话,那个x的坐标就是(7/1壹 * 图片宽度,1/二 *图形中度)

图片 37

假设二个图形变化了,那么这一个j
和i向量就不在是先前相互垂直90度了,然后里面装有的点坐标可能就位移了。

图片 38

譬如本身要把x点移动到b点怎么落到实处吗?

 

图片 39

 

大家得以把地点的直角坐标系想象成一辆公共交通车,全数的点都坐在公共交通车里面,我们在车里未有动,然后公共交通车到达目标地后,大家相对于城市来说已经走了很远很远了。

图片 40

就像那样,x点是否就移动到b点了。

 

首要:所以总结的思绪正是,通过老的直角坐标系的法则获取到每贰个点的岗位,再寻找新的坐标系的规律,把点运动上去,就做到了第3张图片所达到的效劳了

 

上面初步找规律

万一新的图样形成了这么

图片 41

 

是因为多少个顶峰已知,那么那四条边有多少长度,每种边上边包车型地铁点的现实坐标大家就足以确定下来。

图片 42图片 43

 

由上下两条边线确认七个终端,大家就足以确认某七个X坐标上边y的线性别变化化规律。
例如在此以前图片位于x方面四分之一地方的坐标点y方向线性别变化换在新图中的线性别变化换就改成了左图y’.
 
 X坐标固定,那时候大家只要求传入在此之前坐标中的y值,就能博得相对于自身宽度百分之二拾5出的新图中存有的坐标点。

图片 44

由此可见,从前2/肆 四分三等等全体终端方向的y线性别变化换规律我们都足以获得。

下一场大家要做的就是透过轮回遍历出富有向下顶点然后拿走第n个任务处的全部y方向的点,从而得出全部的坐标。然后那1组坐标的就重组了新的图样。

 

末段附上关键代码

//数组包蕴了三回是 左上 右上 右下 左下  六个点地点差别,图片显示的就不一样

 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 superview
18     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     //创建一个bitmapcontext
28     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     //初始化新的图片需要的data
38     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 value
74             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上面的UIImageview
86     _imageView.frame = CGRectMake(minLeft, minTop, shapW, shapH);
87     CGContextRelease(newContext);
88     CGImageRelease(cgImage);
89     free(shapeData);
90 }

 

 

 

相关文章