简体   繁体   English

如何在画布上旋转位图而不使其在 Android 上变形

[英]How to rotate a bitmap on canvas without deform it on Android

I'm rotating a bitmap on the canvas using a matrix as follows:我正在使用矩阵在画布上旋转位图,如下所示:

public void drawRotatedPixmap(Bitmap bitmap, int x, int y, int srcX, int srcY, int srcWidth, int srcHeight, int degrees)
{
    srcRect.left = srcX;
    srcRect.top = srcY;
    srcRect.right = srcX + srcWidth;
    srcRect.bottom = srcY + srcHeight;

    dstRect.left = x;
    dstRect.top = y;
    dstRect.right = x + srcWidth;
    dstRect.bottom = y + srcHeight;

    matrix.reset();
    matrix.setRotate(degrees, x+srcWidth/2, y+srcHeight/2);

    canvas.setMatrix(matrix);               
    canvas.drawBitmap(bitmap, srcRect, dstRect, null);
    canvas.setMatrix(null);
}

The original bitmap image is quite pixelated and rotating it I get this:原始位图图像非常像素化并旋转它我得到了这个:

在此处输入图片说明

By this way the image is rescaling and is quite noticeable at the edges.通过这种方式,图像重新缩放并且在边缘非常明显。 The result I would get is the following:我得到的结果如下:

在此处输入图片说明

It is posibile do this by drawing on the canvas or should I use openGL?可以通过在画布上绘图来做到这一点,还是应该使用 openGL?

Note: sprite image is only for testing and taken from google注意:精灵图片仅供测试使用,取自谷歌

To get higher quality, use a filtered paint:要获得更高的质量,请使用过滤油漆:

Paint filterPaint = new Paint();
filterPaint.setFilterBitmap(true);
canvas.drawBitmap(bitmap, srcRect, dstRect, filterPaint);

The approach you're taking is absolutely fine.你采取的方法绝对没问题。 However it looks to me like the original graphic is already fuzzy - I daresay it has been a JPG at some point in its life.然而,在我看来,原始图形已经模糊不清了——我敢说它在它生命中的某个时刻曾经是一个 JPG。 Note in particular that the edges to the black borders are anti-aliased - they should be black pixels and white pixels but no grey ones.请特别注意,黑色边框的边缘是抗锯齿的 - 它们应该是黑色像素和白色像素,但不是灰色像素。

I believe the rotation algorithm uses sampling to produce the output - this sampling algorithm is interacting with the fuzzy edge producing the undesirable visual artefacts.我相信旋转算法使用采样来产生输出——这种采样算法与产生不良视觉伪影的模糊边缘相互作用。 I bet it will be great if you try again with a sharp original.我敢打赌,如果您再次尝试使用清晰的原件,那会很棒。

There is one more thing to consider: Using a small bitmap and upscaling with rotation.还有一件事需要考虑:使用位图并通过旋转放大。 This might go against the advice of other responders, but bear with me for a minute.这可能与其他响应者的建议背道而驰,但请耐心等待。

The typical scaling algorithm used is typically bi-linear interpolation - it's great for photos but pixelated images look horribly soft.使用的典型缩放算法通常是双线性插值 - 它非常适合照片,但像素化图像看起来非常柔和。 However there are a few other algorithms - go to Wiki: Image Scaling and look at the hqx.但是还有一些其他算法 - 转到Wiki: Image Scaling并查看 hqx。 This is an example of bi-linear vs. HQX in the game space:这是游戏空间中双线性与 HQX 的示例:

这个游戏

If this is acceptable, then we have to go to OpenGL, because the Android Canvas and Bitmap functions don't support these algorithms.如果这是可以接受的,那么我们必须去OpenGL,因为Android Canvas 和Bitmap 函数不支持这些算法。 Potentially a lot of work, but maybe worth your while.可能有很多工作,但也许值得你花时间。

I don't think you can really avoid the pixilating effects with bitmap images.我认为您无法真正避免位图图像的像素化效果。 You might reduce the effect by having a sprite drawn at a very high resolution, doing the rotation and then scale the image down.您可以通过以非常高的分辨率绘制精灵、旋转然后缩小图像来减少效果。 If you have a vector (SVG) version of the image you could rotate that before converting to a bitmap and store a bunch of rotated versions.如果你有一个矢量 (SVG) 版本的图像,你可以在转换为位图之前旋转它并存储一堆旋转的版本。

You should be able to rotate by 90 without pixilating effects.您应该能够在没有像素化效果的情况下旋转 90 度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM