direct2d image viewer如何将屏幕坐标转换为图像坐标?

时间:2013-12-01 21:34:30

标签: matrix transform direct2d invert

我正在试图弄清楚如何将鼠标位置(屏幕坐标)转换为在direct2d表面上绘制的底层变换图像上的相应点。 这里的代码应该被认为是伪代码,因为我正在使用针对c#的direct2d修改过的c ++ / CLI包装器,你将无法在我自己的项目中编译它。

Render()
{
    //The transform matrix combines a rotation, followed by a scaling then a translation
    renderTarget.Transform = _rotate * _scale * _translate;
    RectF imageBounds = new RectF(0, 0, _imageSize.Width, _imageSize.Height);
    renderTarget.DrawBitmap(this._image, imageBounds, 1, BitmapInterpolationMode.Linear);
}
Zoom(float zoomfactor, PointF mousepos)
{
    //mousePos is in screen coordinates. I need to convert it to image coordinates.
    Matrix3x2 t = _translate.Invert();
    Matrix3x2 s = _scale.Invert();
    Matrix3x2 r = _rotate.Invert();
    PointF center = (t * s * r).TransformPoint(mousePos); 
    _scale = Matrix3x2.Scale(zoomfactor, zoomfactor, center);    
}

这是不正确的,当缩放因子平滑地增大或减小时,缩放中心开始疯狂地移动,即使鼠标指针在客户端表面的中心处不动,所得到的缩放功能也不平滑并且闪烁很多。我尝试了所有我能想到的组合,但无法理解。

如果我将刻度中心点设置为(imagewidth / 2,imageheight / 2),则得到的缩放是平滑的,但总是以图像中心为中心,所以我很确定闪烁不是由于其他一些这个程序的错误部分。

感谢。

2 个答案:

答案 0 :(得分:0)

我终于做对了

这让我在客户中心的中心完全平滑(增量?,相对?)缩放 (我放弃了鼠标位置的想法,因为我想使用鼠标移动输入来驱动缩放)

     protected float zoomf
    {
        get
        {
            //extract scale factor from scale matrix
            return (float)Math.Sqrt((double)((_scale.M11 * _scale.M11) 
                                              + (_scale.M21 * _scale.M21)));
        }
    }

    public void Zoom(float factor)
    {

        factor = Math.Min(zoomf, 1) * 0.006f * factor;
        factor += 1;

        Matrix3x2 t = _translation;
        t.Invert();
        PointF center = t.TransformPoint(_clientCenter);


        Matrix3x2 m = Matrix3x2.Scale(new SizeF(factor, factor), center);
        _scale = _scale * m;
        Invalidate();
    }

答案 1 :(得分:0)

Step1:把android:scaleType =" matrix"在ImageView XML文件中 第2步:将屏幕触摸点转换为Matrix值。 第3步:将每个矩阵值除以屏幕密度参数     在所有屏幕中获得相同的坐标值。

**XML**
<ImageView
  android:id="@+id/myImage"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:scaleType="matrix"
  android:src="@drawable/ga"/>

**JAVA**
 @Override
  public boolean onTouchEvent(MotionEvent event) {
    float[] point = new float[]{event.getX(), event.getY()};
    Matrix inverse = new Matrix();
    getImageMatrix().invert(inverse);
    inverse.mapPoints(point);
    float density = getResources().getDisplayMetrics().density;
    int[] imagePointArray = new int[2];
    imagePointArray[0] = (int) (point[0] / density);
    imagePointArray[1] = (int) (point[1] / density);
    Rect rect = new Rect( imagePointArray[0] - 20, imagePointArray[1]  - 20,  imagePointArray[0] + 20, imagePointArray[1]  + 20);//20 is the offset value near to the touch point
        boolean b = rect.contains(267, 40);//267,40 are the predefine image coordiantes
        Log.e("Touch inside ", b + "");
    return true;

}