Android:复制位图

Android:复制位图,android,canvas,bitmap,Android,Canvas,Bitmap,一个看似简单的问题,我有一个屏幕外位图,我对它执行一些转换(旋转、缩放等),我想在转换之前存储一个位图副本,这样在我的视图的onDraw()中,我可以将转换后的屏幕外位图和未转换位图的较小比例版本显示为缩略图 在onDraw()中写入屏幕外位图没有问题,但复制的“保留”位图也正在转换。下面是我制作位图副本的代码,其中mCanvas是通过mCanvas=newcanvas(mBitmap)创建的: 在onDraw()中,我有: // draw the off-screen bitmap to th

一个看似简单的问题,我有一个屏幕外位图,我对它执行一些转换(旋转、缩放等),我想在转换之前存储一个位图副本,这样在我的视图的
onDraw()
中,我可以将转换后的屏幕外位图和未转换位图的较小比例版本显示为缩略图

onDraw()
中写入屏幕外位图没有问题,但复制的“保留”位图也正在转换。下面是我制作位图副本的代码,其中mCanvas是通过
mCanvas=newcanvas(mBitmap)创建的

在onDraw()中,我有:

// draw the off-screen bitmap to the on-screen bitmap
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

// draw the preserved image, scaling it to a thumbnail first
canvas.drawBitmap(
    Bitmap.createScaledBitmap(mPreservedBitmap, (int) thumbWidth, (int) thumbHeight, true), 
null, 
thumbnailRectF, 
thumbCanvasPaint);
缩略图会被缩放到适当的大小,但是正在被缩放到缩略图大小的位图也会被旋转和缩放到与mBitmap完全相同的位置,这是我不想要的。我还尝试了Bitmap.copy()方法,但结果相同。有什么建议/帮助/建议吗

谢谢

Paul

你做错了:)首先,你不应该在字段中保留对画布的引用。无法保证画布实例在对onDraw()的两个不同调用中是相同的。第二个问题是如何应用转换。您应该在onDraw()中应用它们:

invalidate()不是一个同步操作,如果在onDraw()之外执行,则save()/restore()不能保证工作


另外,不要从onDraw()调用createScaledBitmap(),这非常昂贵。

要展开我的评论:

Bitmap.createBitmap(位图)
返回一个不可变的位图。文档实际上说它可能是相同的对象或使用相同的数据。 如果确实要修改位图,则必须创建可变位图,例如:

mPreservedBitmap = mBitmap;

// Create a new, empty bitmap with the original size.
// Since the image is going to be scaled, this might be to big or to small.
// Rotating might also require additional space (otherwise the corners will be cut off)
// Try calculating the proper size or play around with some other createBitmap Methods, just make sure to
// actually create a mutable bitmap, for example by using copy on an immutable bitmap.
mBitmap = Bitmap.createBitmap(mPreservedBitmap.getWidth(), mPreservedBitmap.getHeight(), mPreservedBitmap.getConfig());

mCanvas = new Canvas(mBitmap);

// do some rotations, scaling
mCanvas.rotate(rotation, px, py);
mCanvas.scale(scaleFactor, scaleFactor, scaleFocusX, scaleFocusY);

// draw the original image to the canvas, applying the matrix modifications
mCanvas.drawBitmap(mPreservedBitmap, 0, 0, null);
在昂德劳:

canvas.save();
canvas.rotate(rotation, px, py);
canvas.scale(scaleFactor, scaleFactor, scaleFocusX, scaleFocusY);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.restore();

canvas.drawBitmap(
    Bitmap.createScaledBitmap(mPreservedBitmap, (int) thumbWidth, (int) thumbHeight, true), null, thumbnailRectF, thumbCanvasPaint);
// draw the off-screen bitmap to the on-screen bitmap
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);

// draw the preserved image, scaling it to a thumbnail
canvas.drawBitmap(mPreservedBitmap, null, thumbnailRectF, thumbCanvasPaint);

我的最终解决方案是,在通过以下方式缩放画布之前,生成画布
位图的副本:

mPreservedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), null, true);
然后,当缩放
画布
和主位图时,我可以通过以下方式将未缩放的“保留”位图
绘制到
onDraw()中的
画布

canvas.drawBitmap(mPreservedBitmap, null, thumbnailRectF, thumbCanvasPaint);

根据Romain上面的评论,我在
onDraw()

中缩放保留的
位图
屏幕外以提高性能第一个片段中的mCanvas还有什么其他操作吗?它实际上似乎没有做任何事情(旋转等只会影响未来的操作,而不会影响图像本身)。为什么要在onDraw中复制位图?通过适当修改画布的矩阵,您应该能够动态缩放缩略图。我正在代码中的其他点使用mCanvas将用户绘制的完整形状添加到屏幕外位图中。我确实可以将createScaledBitmap代码移出onDraw,我只是在那里测试复制/缩放。谢谢Romain。我将在两个不同的评论中作出回应。如果不是对画布的字段引用(用于访问屏幕外mBitmap),如何重复写入位图?这是一个绘图程序,当用户完成图形时,将完成的图形提交到屏幕外位图;当用户绘制一个进行中的形状时,我调用onDraw(),一旦形状完成,它就会通过mCanvas累积添加到mBitmap中。每次我希望访问mBitmap
Canvas Canvas=newcanvas(mBitmap)时,是否应该创建新的画布引用?就在onDraw()中执行旋转和缩放而言,我最初是这样设置的,但当用户在屏幕上绘制当前形状时,我调用onDraw时,需要动态旋转/缩放屏幕外位图以获得n个可能的x/y对,这是非常缓慢的。我对它进行了设置,这样当用户进行缩放时,整个屏幕外位图会在屏幕外重新绘制,然后在onDraw()中闪烁到画布上。但是,如果用户已完成缩放并按比例绘制,我只需调用onDraw并使用已缩放的屏幕外位图。作为另一个后续操作,我已将代码切换回onDraw(),以便在onDraw()中进行旋转和缩放。。。而且表演相当残酷。当用户处于画布正在旋转的状态,并且在绘制时缩放画布,并调用onDraw()显示进度时,延迟/性能是无法使用的。我一定是遗漏了什么。如果使用mCanvas在位图中绘制,您可以保留对它的引用。但如果不在内部绘制,仍然无法执行save()/restore()。没什么用。/接下来,我根据API演示FingerPaint.java对其进行建模,它确实使用字段中的画布绘制屏幕外位图。绘图路径上有没有不使用画布字段的指针?谢谢嗯,尝试过这个,但是mPreservedBitmap被设置为mBitmap的缩放版本。。。
canvas.drawBitmap(mPreservedBitmap, null, thumbnailRectF, thumbCanvasPaint);