Смещение растрового изображения только в вертикальном направлении


Я хочу исказить (поправьте меня, если это не правильное слово) растровое изображение, чтобы оно казалось глубоким. Хороший способ визуализировать то, что я прошу, - это как титры "Звездных войн" наклонены, чтобы показать глубину.

Я попробовал следующее:

canvas.getMatrix().postSkew(kx,ky,px,py);

И

canvas.skew(sx,sy);
Но у меня не было большого успеха. Приведенные выше методы, по-видимому, всегда преобразуют растровое изображение в параллелограмм. Есть ли способ преобразовать растровое изображение в трапецию?

Вот фрагмент кода, который я взял из примеров, на которые указал мне Ромен.

canvas.rotate(-mOrientation[0] + mHeading, mCenterX, mCenterY);

camera.save();

if (mReverse) {
    camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
    camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}

camera.rotateX(mOrientation[1]);
camera.applyToCanvas(canvas);
canvas.drawPath(mPath, mPaint);
canvas.drawCircle(mCenterX, mCenterY, mRadius - 37, mPaint);

camera.restore();
3 8

3 ответа:

Вы не можете достичь желаемого эффекта с помощью функции skew (). Однако для достижения этого эффекта можно использовать объект камеры и 3D-вращения. Камера сгенерирует матрицу для вас, которую вы затем можете применить на холсте. Обратите внимание, что результат не будет перспективно правильным, но достаточно хорошим для вашей цели. Так, например, выполняются 3D-вращения в лаунчере Honeycomb (и многих других приложениях.)

Я потратил много времени, работая над этим сегодня (столкнулся с той же проблемой) и придумал код ниже.

Ключевая вещь, которую нужно отметить, вам нужно установить preTranslate() и postTranslate() в центре (или где-то еще) Вашей области холста. Это, по-видимому, означает,что он использует центр изображения для применения преобразования из, а не верхний левый угол (x=0, y=0) по умолчанию. Вот почему вы получите параллелограмм вместо того, что вы ожидали бы, трапеция (Спасибо за учит меня их именам).

Еще одна важная вещь, которую я подобрал, - это функции сохранения/восстановления на холсте/камере. В принципе, если вы вызываете функции поворота последовательно три раза без восстановления состояния каждый раз, вы будете продолжать вращать свой объект вокруг и вокруг каждый раз, когда вы рисуете. Может быть, вы этого и хотите, но в моем случае я этого не делал. То же самое относится и к холсту, поскольку вы в основном применяете матрицу от объекта камеры к холсту и его нужно сбросить, иначе произойдет то же самое.

Надеюсь, это кому-то поможет, это не очень хорошо документировано для начинающих. Совет всем, кто читает это, проверьте папку APIDemos в образцах SDK. Существует Rotate3dAnimation.java-файл, который также демонстрирует это.

//Snippet from a function used to handle a draw
mCanvas.save(); //save a 'clean' matrix that doesn't have any camera rotation in it's matrix
ApplyMatrix(); //apply rotated matrix to canvas
Draw(); //Does drawing
mCanvas.restore(); //restore clean matrix
//    

public void ApplyMatrix() {
  mCamera.save();
  mCamera.rotateX(-66);
  mCamera.rotateY(0);
  mCamera.rotateZ(0);
  mCamera.getMatrix(mMatrix);

  int CenterX = mWidth / 2;
  int CenterY = mHeight / 2; 
  mMatrix.preTranslate(-CenterX, -CenterY); //This is the key to getting the correct viewing perspective
  mMatrix.postTranslate(CenterX, CenterY); 

  mCanvas.concat(mMatrix);
  mCamera.restore();    
}

Я не думаю, что "эффект Звездных войн" является аффинным преобразованием , которое, по-моему, является единственной операцией, поддерживаемой Matrix.