1、回顧
? ? ? ?上一節中,我們實現一個UIImageView的移動,放縮,旋轉,并把這些數據存儲在Transform
屬性里面,但我們知道,這些數據只是用于當前低畫質的圖片,而我們需要的是處理原圖(高品質的圖片)。因此,這一節,我們將實現如何把Tranform
屬性應用在原圖上面。
2、畫圖
? ? ? ?很容易,我們便相當了畫圖的功能,自然而然想到了CoreGraphics
,然后我查了查API,很高興,CoreGraphics
也有矩陣應用API,如:
CGContextTranslateCTM
CGContextConcatCTM
……
? ? ? ?那直接開干,創建一個類 UIImage+Extensions
- (UIImage *)handleOriginImage:(CGAffineTransform)transform{
UIGraphicsBeginImageContext(self.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextConcatCTM(context, transform);
//self 即當前的UIImage
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
UIImage *copy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return copy;
}
? ? ? ?感覺對的啊。沒有問題,但運行結果和期望的大相徑庭,不知道什么原因??!通過慢慢排查,你會發現是 定點 在搞鬼。
? ? ? ?我們都知道的在 UIImageView 進行旋轉放縮的時候,我們默認設置的是 UIImageView 的中心點為定點 anchor Point,而你在作圖的時候,你會驚奇的發現,畫圖的定點一直是左上角,所以旋轉和放縮之后,得到的結果相差很大。
? ? ? ?那自然而然,想到,該如何改變畫布的定點,可惜我找了大半天也沒找到。??赡苁俏姨酰坑邪l現的大神請告訴我?。?!那難道,我只能把 UIImageView 操作的時候的定點,設置到左上角?那樣體驗也太不好了吧。。。
? ? ? ?后來想到,記得上一節,在圖片移動的時候,我們用過三角函數,進行變換,那當然我們這兒也可以。坐標系東西都可以用數學知識進行改變的。
3、解決方案
圖示:
? ? ? ?我可以先把圖片移動到特定的位置,讓其按左上角旋轉之后的結果,和在原始位置按中心點旋轉的結果一樣。(為什么不在圖片旋轉之后再移動位置呢?如上節說過,圖片矩陣旋轉,會改變坐標系,那時候的移動得相對于那時的坐標系,操作起來更加繁瑣!因此,我們在最初進行坐標移動矯正,然后應用矩陣)
- (UIImage *)handleOriginImage:(CGAffineTransform)transform scale:(CGFloat)scale{
UIGraphicsBeginImageContext(self.size);
CGContextRef context = UIGraphicsGetCurrentContext();
//先計算出操作圖的旋轉角度和放縮比例
CGFloat editDegree = atan2(transform.b, transform.a);
CGFloat editScale = sqrt(pow(transform.a, 2) + pow(transform.c, 2));
//通過計算,在操作之前,修正左上角的位置
CGFloat diameter = sqrt(pow(self.size.width, 2)+pow(self.size.height, 2));
CGFloat originDegree = asin(self.size.height / diameter);
CGFloat currentDegree = originDegree + editDegree;
CGFloat newX = self.size.width / 2 - cos(currentDegree) * diameter * editScale / 2;
CGFloat newY = self.size.height / 2 - sin(currentDegree) * diameter * editScale/ 2;
//水平的操作,在原圖上進行修正,tx,ty分別代表 X,Y軸移動的距離
transform.tx = transform.tx * scale;
transform.ty = transform.ty * scale;
//先修正左上角的位置
CGContextTranslateCTM(context, newX, newY);
//對3*3矩陣進行渲染
CGContextConcatCTM(context, transform);
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
UIImage *copy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return copy;
}
? ? ? ?代碼很清楚,一點需要解釋: //水平的操作,在原圖上進行修正 這部分的代碼,因為在UIImageView上面做的操作,比如當時圖片是 100 * 100, 原圖是1000 * 1000,所以當時的移動距離,在原圖上面應該放大10倍,所以這里主要做這個處理。