androidmatrix旋轉
『壹』 如何解決Android三星手機從圖庫選擇照片旋轉問題
最近解決了一個令我頭疼好久的問題,就是三星手機拍照圖片旋轉的問題,項目中有上傳圖片的功能,那麼涉及到拍照,從相冊中選擇圖片,別的'手機都ok沒有問題,唯獨三星的手機拍照之後,你會很清楚的看到會把照片旋轉一下,然後你根據路徑找到的圖片就是已經被旋轉的了,解決辦法終於被我找到了。我們可以根據圖片的路徑讀取照片exif(Exchangeable Image File 可交換圖像文件)信息中的旋轉角度,至於這個EXIF可以看一下大牛的文章
Android 下的EXIF
根據調試,可以清楚的發現三星手機拍照的圖片的旋轉角度是90度,而別的手機旋轉角度是0度
看一下代碼:
/** * 讀取照片exif信息中的旋轉角度 * @param path 照片路徑 * @return角度 */ public static int readPictureDegree(String path) { int degree = 0; try { ExifInterface exifInterface = new ExifInterface(path); int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) { case ExifInterface.ORIENTATION_ROTATE_90: degree = 90; break; case ExifInterface.ORIENTATION_ROTATE_180: degree = 180; break; case ExifInterface.ORIENTATION_ROTATE_270: degree = 270; break; } } catch (IOException e) { e.printStackTrace(); } return degree; }
那麼我們只需要根據旋轉角度將圖片旋轉過來就OK了
public static Bitmap toturn(Bitmap img){ Matrix matrix = new Matrix(); matrix.postRotate(+90); /*翻轉90度*/ int width = img.getWidth(); int height =img.getHeight(); img = Bitmap.createBitmap(img, 0, 0, width, height, matrix, true); return img; }
輕松解決了,是不是很完美?
以上就是本文的全部內容,希望大家喜歡。
『貳』 android 中用畫布旋轉圖片的時候怎麼讓讓他 圍著一個坐標旋轉
方法只有一種。
步驟:
1、畫布平移坐標原點
2、旋轉畫布
示例代碼
java">canvas.save();//保存當前畫布狀態
canvas.translate(x,y);//將坐標中心平移到要圍繞的坐標點x,y
canvas.rotate(90);//旋轉角度,這里比如90度
canvas.restore();//恢復畫圖狀態到保存前
『叄』 Android自定義控制項之可平移、縮放、旋轉圖片控制項
先上效果圖
單點拖動圖片對圖片進行平移操作。雙手縮放圖片大小和旋轉圖片到一定的角度。圖片縮放的時候 不能大於最大的縮放因子和小於最小的縮放因子。大於最大縮放因子或者小於最小縮放因子需要對圖像進行回彈。圖片旋轉的角度只能為90度的倍數,不滿足90度要進行回彈。圖片回彈要一個漸變的效果。
大體思路: 首先,Android中提供了Matrix類可以對圖像進行處理。其次,要顯示一張圖片最容易想到的就是ImageView。回彈要求漸變的過程,可以通過屬性動畫進行設置。所以大體的思路是:繼承ImageView,重寫onTouchEvent()方法,判斷事件類型,在對應的事件使用Matrix對圖像進行變換。
Matrix是一個已經封裝好的矩陣,最重要的作用就是對坐標點進行變換。
舉個栗子:
1.某個點(x0,y0,1)通過單位矩陣E映射得到的點還是(x0,y0,1)。
3.點(x0,y0,1)通過矩陣T映射得到的點就會做如下的變換
可以看到點(x0,y0,1)經過T矩陣在x軸方向上平移了dx,在y軸方向上平移了dy。
通過以上的變換可以得到具體的思路: 我們維護一個圖像對應的矩陣mCurrentMatrix,該矩陣主要是對ImageView中的圖像的各個點進行映射。ImageView在容器位置擺放完成之後,置mCurrentMatrix矩陣為單位矩陣。當onTouchEvent()方法中觸發單點觸控並且手指進行平移的時候,調用矩陣mCurrentMatrix的postTranslate(dx,dy),對mCurrentMatrix進行變換。當手指抬起,利用變換結束後的矩陣對圖像的各個點進行映射,從而得到平移變換後的圖像。同理可得,在兩只手指進行縮放旋轉的時候,我們對矩陣mCurrentMatrix進行各種變換,當縮放旋轉的事件結束再利用變換完的矩陣去映射圖像的各個點,從而得到縮放、旋轉後的圖像。
安卓自定義View進階 - Matrix原理
安卓自定義View進階 - Matrix詳解
首先理清事件的邏輯:
初始化圖像大小和位置
縮放圖像大小和控制項大小自適應,平移圖像中心和控制項中心重合
onTouchEvent()函數
平移操作
將圖像對應的矩陣進行變換。
縮放操作
mBoundRectF為記錄圖像邊界的矩形。縮放的時候選取圖像的中心進行縮放。
旋轉操作
旋轉的時候旋轉的旋轉中心也是圖像的中心
圖像中各個點的映射
調用ImageView的setImageMatrix(Matrix matrix)會讓ImageView根據設置的matrix去重新繪制圖像。
更新圖像的矩形邊界
獲得圖像的矩形,並根據矩陣映射矩形各個點的坐標。
縮放回彈
旋轉回彈
一些計算方法
要求圖像的變換是一個漸變的過程,很容易想到的就是屬性動畫。因為屬性動畫本身就是對值進行不斷set的過程。而我們維護的矩陣也是一個值,所以很自然可以想到,如果得到回彈之前的矩陣的值以及回彈之後矩陣的值,就可以根據動畫監聽器中動畫當前的系數值去改變矩陣的值。
對animator對象設置完監聽器之後,就可以在手指抬起的時候調用屬性動畫的start()方法開啟動畫。
自定義可平移、縮放、旋轉的控制項主要點有兩個方面:一是onTouchEvent()中判斷平移、旋轉、縮放的觸發條件,平移位移量、縮放比例因子、旋轉角度的計算。二是Matrix矩陣的應用。
『肆』 android怎麼實現圖片旋轉
可以使用RotateAnimation動畫實現,設定無限循環即可
代碼如下
{
ImageViewiv;
@Override
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);
iv=(ImageView)findViewById(R.id.image);
RotateAnimationanimation=newRotateAnimation(0,360);
animation.setDuration(100000);//設定轉一圈的時間
animation.setRepeatCount(Animation.INFINITE);//設定無限循環
animation.setRepeatMode(Animation.RESTART);
iv.startAnimation(animation);
}
}
也可以自定義view繼承於imageview,啟動一個線程,在while循環里設置view的旋轉角度
{
privatefloatmCurDegree=0;//當前旋轉角度
publicRotateView(Contextcontext,AttributeSetattrs){
super(context,attrs);
newThread(this).start();
}
@Override
protectedvoidonLayout(booleanchanged,intleft,inttop,intright,
intbottom){
super.onLayout(changed,left,top,right,bottom);
//設定旋轉中心
setPivotX(getMeasuredWidth()/2);
setPivotY(getMeasuredHeight()/2);
}
@Override
publicvoidrun(){
while(true){
setRotation(mCurDegree);
mCurDegree+=5;
postInvalidate();
SystemClock.sleep(16);
}
}
}
在布局文件里使用RotateView代替imageview即可
『伍』 android 怎麼讓圖片實現朝Z軸的方向旋轉RotateAnimation是x y方向的,我想要包含z方向的
RotateAnimation是不可以繞Z軸旋轉的,如果LZ想要實現Z軸旋轉效果,可以看下matrix這個類(實際還是opengl),可以給LZ例舉下:
rotateX(float degree) 繞著x軸旋轉degree個度數
rotateY(float degree) 繞著y軸旋轉degree個度數
rotateZ(float degree) 繞著z軸旋轉degree個度數
『陸』 Android中的Matrix,以及set,pre和post的區別
Matrix包含一個3 X 3的矩陣,專門用於圖像變換匹配。
Matrix提供了四種操作:
translate(平移)
rotate(旋轉)
scale(縮放)
skew(傾斜)
也就是說這4種操作都是對這個3 X 3的矩陣設值來達到變換的效果。
Matrix沒有結構體,它必須被初始化,通過reset或set方法。
OK,Matrix介紹完了,我們來看看set、pre、post的區別。
pre是在隊列最前面插入,post是在隊列最後面追加,而set先清空隊列在添加(這也是上文提到的「Matrix沒有結構體,它必須被初始化,通過reset或set方法」的原因)。
下面通過一些例子具體說明:
matrix.preScale(2f,1f);
matrix.preTranslate(5f, 0f);
matrix.postScale(0.2f, 1f);
matrix.postTranslate(0.5f, 0f);
執行順序:translate(5, 0) -> scale(2f, 1f) -> scale(0.2f, 1f) -> translate(0.5f, 0f)
matrix.postTranslate(2f, 0f);
matrix.preScale(0.2f, 1f);
matrix.setScale(1f, 1f);
matrix.postScale(5f, 1f);
matrix.preTranslate(0.5f, 0f);
執行順序:translate(0.5f, 0f) -> scale(1f, 1f) -> scale(5f, 1)
『柒』 android Matrix.setRotate 和 postRotate的區別
Matrix主要用於對平面進行平移(Translate),縮放(Scale),旋轉(Rotate)以及斜切(Skew)操作。
為簡化矩陣變換,Android封裝了一系列方法來進行矩陣變換;其中包括:
set系列方法:setTranslate,setScale,setRotate,setSkew;設置,會覆蓋之前的參數。
pre系列方法:preTranslate,preScale,preRotate,preSkew;矩陣先乘,如M' = M * T(dx, dy)。
post系列方法:postTranslate,postScale,postRotate,postSkew;矩陣後乘,如M' = T(dx, dy) * M。
通過將變換矩陣與原始矩陣相乘來達到變換的目的,例如:
平移(x'=x+tx;y'=y+ty):
縮放(x'=sx*x;y'=sy*y):
旋轉(x'=cosβ*x-sinβ*y;y'=sinβ*x+cosβ*y):
選擇需要用到如下的三角函數的公式:
①sin(α+β)=sinαcosβ+cosαsinβ
②cos(α+β)=cosαcosβ-sinαsinβ
公式①可以由單位圓方法或托勒密定理推導出來。
推導過程參見:http://blog.sina.com.cn/s/blog_58260f420100c03j.html
斜切(x'=x+k1*y;y'=k2*x+y):
//源碼文件:external\skia\legacy\src\core\SkMatrix.cpp
#define SK_Scalar1 (1.0f)
#define kMatrix22Elem SK_Scalar1
typedef float SkScalar;
#define SkScalarMul(a, b) ((float)(a) * (b))
enum {
kMScaleX, kMSkewX, kMTransX,
kMSkewY, kMScaleY, kMTransY,
kMPersp0, kMPersp1, kMPersp2
};
void SkMatrix::reset() {
fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; //其值為1
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMTransX] = fMat[kMTransY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; //其值,全為0
fMat[kMPersp2] = kMatrix22Elem; //其值為1
this->setTypeMask(kIdentity_Mask | kRectStaysRect_Mask);
}
void SkMatrix::setTranslate(SkScalar dx, SkScalar dy) {
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] = dx; //以新值dx覆蓋原值,原值無效了
fMat[kMTransY] = dy;
fMat[kMScaleX] = fMat[kMScaleY] = SK_Scalar1; //其值為1
fMat[kMSkewX] = fMat[kMSkewY] =
fMat[kMPersp0] = fMat[kMPersp1] = 0; //其值,全為0
fMat[kMPersp2] = kMatrix22Elem; //其值為1
this->setTypeMask(kTranslate_Mask | kRectStaysRect_Mask);
} else {
this->reset();
}
}
bool SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
return this->preConcat(m); //矩陣的先乘運算
}
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] += SkScalarMul(fMat[kMScaleX], dx) +
SkScalarMul(fMat[kMSkewX], dy); //先乘,需要矩陣運算過
fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
SkScalarMul(fMat[kMScaleY], dy);
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
return true;
}
bool SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
if (this->hasPerspective()) {
SkMatrix m;
m.setTranslate(dx, dy);
return this->postConcat(m); //矩陣的後乘運算
}
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] += dx; //後乘,直接加新值dx即可
fMat[kMTransY] += dy;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
return true;
}
bool SkMatrix::preConcat(
『捌』 android 圖片旋轉
Android UI之ImageView旋轉的幾種方式
Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.drawable.ic_launcher)).getBitmap();
Matrix matrix = new Matrix();
matrix.setRotate(90);
Bitmap new = Bitmap.create(bitmap,0,bitmap.getWidth(),0,bitmap.getHeight(),matrix);
image.setBitmapResource(bitmap);
如果程序不斷獲取新的bitmap重新設置給ImageView的話,那麼bitmap在含慶不斷旋轉,談悄握又不回收內存,浪費大大噠,不推薦使用。
可以通過在xml中設置ImageView的屬性來實現,如
android:rotation="90" //寫死固定方向沒問題運指
,這樣。
動態調用如下:
iv.setPivotX(image.getWidth()/2);
iv.setPivotY(image.getHeight()/2);//支點在圖片中心
iv.setRotation(90);
可以使用ImageView配合屬性動畫實現,如
iv.animate().rotation(90); //會好看一下,只有第一次載入時是這樣的
或者普通動畫
Animation rotateAnimation = new RotateAnimation(lastAngle, progress, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 1);
rotateAnimation.setFillAfter(true);
rotateAnimation.setDuration(50);
rotateAnimation.setRepeatCount(0);
rotateAnimation.setInterpolator(new LinearInterpolator());
rotateImage.startAnimation(rotateAnimation);
Matrix matrix=new Matrix();
rotateImage.setScaleType(ScaleType.MATRIX); //required
matrix.postRotate((float) progress, pivotX, pivotY);
iv.setImageMatrix(matrix);