1蛤织、回顧
? ? ? ?上一節(jié)中赴叹,我們實(shí)現(xiàn)一個(gè)UIImageView的移動(dòng),放縮指蚜,旋轉(zhuǎn)乞巧,并把這些數(shù)據(jù)存儲(chǔ)在Transform
屬性里面,但我們知道摊鸡,這些數(shù)據(jù)只是用于當(dāng)前低畫質(zhì)的圖片绽媒,而我們需要的是處理原圖(高品質(zhì)的圖片)。因此免猾,這一節(jié)是辕,我們將實(shí)現(xiàn)如何把Tranform
屬性應(yīng)用在原圖上面。
2猎提、畫圖
? ? ? ?很容易获三,我們便相當(dāng)了畫圖的功能,自然而然想到了CoreGraphics
锨苏,然后我查了查API疙教,很高興,CoreGraphics
也有矩陣應(yīng)用API伞租,如:
CGContextTranslateCTM
CGContextConcatCTM
……
? ? ? ?那直接開(kāi)干,創(chuàng)建一個(gè)類 UIImage+Extensions
- (UIImage *)handleOriginImage:(CGAffineTransform)transform{
UIGraphicsBeginImageContext(self.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextConcatCTM(context, transform);
//self 即當(dāng)前的UIImage
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
UIImage *copy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return copy;
}
? ? ? ?感覺(jué)對(duì)的啊贞谓。沒(méi)有問(wèn)題,但運(yùn)行結(jié)果和期望的大相徑庭肯夏,不知道什么原因>辍!通過(guò)慢慢排查驯击,你會(huì)發(fā)現(xiàn)是 定點(diǎn) 在搞鬼烁兰。
? ? ? ?我們都知道的在 UIImageView 進(jìn)行旋轉(zhuǎn)放縮的時(shí)候,我們默認(rèn)設(shè)置的是 UIImageView 的中心點(diǎn)為定點(diǎn) anchor Point徊都,而你在作圖的時(shí)候沪斟,你會(huì)驚奇的發(fā)現(xiàn),畫圖的定點(diǎn)一直是左上角暇矫,所以旋轉(zhuǎn)和放縮之后主之,得到的結(jié)果相差很大。
? ? ? ?那自然而然李根,想到槽奕,該如何改變畫布的定點(diǎn),可惜我找了大半天也沒(méi)找到房轿。粤攒∷可能是我太弱?有發(fā)現(xiàn)的大神請(qǐng)告訴我:唤印;兰谩!那難道盔几,我只能把 UIImageView 操作的時(shí)候的定點(diǎn)晴弃,設(shè)置到左上角?那樣體驗(yàn)也太不好了吧逊拍。上鞠。。
? ? ? ?后來(lái)想到芯丧,記得上一節(jié)旗国,在圖片移動(dòng)的時(shí)候,我們用過(guò)三角函數(shù)注整,進(jìn)行變換,那當(dāng)然我們這兒也可以度硝。坐標(biāo)系東西都可以用數(shù)學(xué)知識(shí)進(jìn)行改變的肿轨。
3、解決方案
圖示:
? ? ? ?我可以先把圖片移動(dòng)到特定的位置蕊程,讓其按左上角旋轉(zhuǎn)之后的結(jié)果椒袍,和在原始位置按中心點(diǎn)旋轉(zhuǎn)的結(jié)果一樣。(為什么不在圖片旋轉(zhuǎn)之后再移動(dòng)位置呢藻茂?如上節(jié)說(shuō)過(guò)驹暑,圖片矩陣旋轉(zhuǎn),會(huì)改變坐標(biāo)系辨赐,那時(shí)候的移動(dòng)得相對(duì)于那時(shí)的坐標(biāo)系优俘,操作起來(lái)更加繁瑣!因此掀序,我們?cè)谧畛踹M(jìn)行坐標(biāo)移動(dòng)矯正帆焕,然后應(yīng)用矩陣)
- (UIImage *)handleOriginImage:(CGAffineTransform)transform scale:(CGFloat)scale{
UIGraphicsBeginImageContext(self.size);
CGContextRef context = UIGraphicsGetCurrentContext();
//先計(jì)算出操作圖的旋轉(zhuǎn)角度和放縮比例
CGFloat editDegree = atan2(transform.b, transform.a);
CGFloat editScale = sqrt(pow(transform.a, 2) + pow(transform.c, 2));
//通過(guò)計(jì)算,在操作之前不恭,修正左上角的位置
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;
//水平的操作叶雹,在原圖上進(jìn)行修正,tx换吧,ty分別代表 X,Y軸移動(dòng)的距離
transform.tx = transform.tx * scale;
transform.ty = transform.ty * scale;
//先修正左上角的位置
CGContextTranslateCTM(context, newX, newY);
//對(duì)3*3矩陣進(jìn)行渲染
CGContextConcatCTM(context, transform);
[self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
UIImage *copy = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return copy;
}
? ? ? ?代碼很清楚折晦,一點(diǎn)需要解釋: //水平的操作,在原圖上進(jìn)行修正 這部分的代碼沾瓦,因?yàn)樵赨IImageView上面做的操作满着,比如當(dāng)時(shí)圖片是 100 * 100谦炒, 原圖是1000 * 1000,所以當(dāng)時(shí)的移動(dòng)距離漓滔,在原圖上面應(yīng)該放大10倍编饺,所以這里主要做這個(gè)處理。