Xamarin.Andoid: 将 ImageView 与 CanvasView 合并
Xamarin.Andoid: Merge ImageView with CanvasView
我正在使用来自 this xamarin sample 的 FingerPaintCanvasView。
我正在使用 2 层 。第一层是我要绘制的 ImageView。第二层是PaintCanvasView来绘制。
<RelativeLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<ImageView
android:id="@+id/markImageImageView"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<fingerpaint.FingerPaintCanvasView
android:id="@+id/canvasMarkMeta"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
canvas 具有透明背景,并且两个视图的布局参数均以编程方式设置。这样标记就可以正常工作了。
现在的问题是,我怎样才能将这个图像视图与标记 canvas 合并到一个单一文件(文件系统中的位图或图像文件)的质量损失尽可能小。
让我解释一下为什么我提到了质量损失:
例如,背景中的图像在设备相机中的尺寸为 1920x1080。显示器只有 1280x800 像素。由于我无法在显示器中显示图像,我需要显示缩小版本并且标记发生在这个缩小版本上。
编辑:
@Joe LV:
这是您的演示,没有在我的设备上部署任何更改:
联想瑜伽3,Android6.0.1
华为荣耀8,Android7.0
我会尽快尝试 Android 8 模拟器。
像素 2XL,Android8.1
所以这个方法不适用于API <= 24 :-(
(API 25 和 26 未测试)
markImageImageView
只保存我从设备存储加载的图像(可以是任何图像)
canvasMarkMeta
是链接模板中的 FingerPaintCanvas,它保存绘制的线条。
下面是代码,我在里面添加了注释:
public class MainActivity : Activity
{
private Rect mSrcRect, mDestRect;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
//your background picture ---markImageImageView
Bitmap background = BitmapFactory.DecodeResource(Resources, Resource.Drawable.pause);
//your foreground picture ---FingerPaintCanvasView
Bitmap foreground = BitmapFactory.DecodeResource(Resources, Resource.Drawable.play);
Paint p = new Paint();
p.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.SrcOver));
//use background to create a canvas
Bitmap workingBitmap = Bitmap.CreateBitmap(background);
Bitmap mutableBitmap = workingBitmap.Copy(Bitmap.Config.Argb8888, true);
Canvas c = new Canvas(mutableBitmap);
int mBWith = background.Width;
int mBHeight = background.Height;
int mFWith = foreground.Width;
int mFHeight = foreground.Height;
mSrcRect = new Rect(0, 0, mBWith, mBHeight);
mDestRect = new Rect(0, 0, mFWith, mFHeight);
//draw foreground on the backaground, then they will be single bitmap
c.DrawBitmap(foreground, mSrcRect, mDestRect, p);
ImageView imageView = FindViewById<ImageView>(Resource.Id.iv);
imageView.SetImageBitmap(mutableBitmap);
}
}
而且我已经在 github 上提供了 demo。
更新:
将 Bitmap.Config.Argb4444
更改为 Bitmap.Config.Argb8888
。
我正在使用来自 this xamarin sample 的 FingerPaintCanvasView。
我正在使用 2 层 。第一层是我要绘制的 ImageView。第二层是PaintCanvasView来绘制。
<RelativeLayout
android:layout_height="match_parent"
android:layout_width="match_parent">
<ImageView
android:id="@+id/markImageImageView"
android:layout_height="wrap_content"
android:layout_width="wrap_content"/>
<fingerpaint.FingerPaintCanvasView
android:id="@+id/canvasMarkMeta"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
canvas 具有透明背景,并且两个视图的布局参数均以编程方式设置。这样标记就可以正常工作了。
现在的问题是,我怎样才能将这个图像视图与标记 canvas 合并到一个单一文件(文件系统中的位图或图像文件)的质量损失尽可能小。
让我解释一下为什么我提到了质量损失: 例如,背景中的图像在设备相机中的尺寸为 1920x1080。显示器只有 1280x800 像素。由于我无法在显示器中显示图像,我需要显示缩小版本并且标记发生在这个缩小版本上。
编辑:
@Joe LV:
这是您的演示,没有在我的设备上部署任何更改:
联想瑜伽3,Android6.0.1
华为荣耀8,Android7.0
我会尽快尝试 Android 8 模拟器。
像素 2XL,Android8.1
所以这个方法不适用于API <= 24 :-( (API 25 和 26 未测试)
markImageImageView
只保存我从设备存储加载的图像(可以是任何图像)
canvasMarkMeta
是链接模板中的 FingerPaintCanvas,它保存绘制的线条。
下面是代码,我在里面添加了注释:
public class MainActivity : Activity
{
private Rect mSrcRect, mDestRect;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
//your background picture ---markImageImageView
Bitmap background = BitmapFactory.DecodeResource(Resources, Resource.Drawable.pause);
//your foreground picture ---FingerPaintCanvasView
Bitmap foreground = BitmapFactory.DecodeResource(Resources, Resource.Drawable.play);
Paint p = new Paint();
p.SetXfermode(new PorterDuffXfermode(PorterDuff.Mode.SrcOver));
//use background to create a canvas
Bitmap workingBitmap = Bitmap.CreateBitmap(background);
Bitmap mutableBitmap = workingBitmap.Copy(Bitmap.Config.Argb8888, true);
Canvas c = new Canvas(mutableBitmap);
int mBWith = background.Width;
int mBHeight = background.Height;
int mFWith = foreground.Width;
int mFHeight = foreground.Height;
mSrcRect = new Rect(0, 0, mBWith, mBHeight);
mDestRect = new Rect(0, 0, mFWith, mFHeight);
//draw foreground on the backaground, then they will be single bitmap
c.DrawBitmap(foreground, mSrcRect, mDestRect, p);
ImageView imageView = FindViewById<ImageView>(Resource.Id.iv);
imageView.SetImageBitmap(mutableBitmap);
}
}
而且我已经在 github 上提供了 demo。
更新:
将 Bitmap.Config.Argb4444
更改为 Bitmap.Config.Argb8888
。