Java 保存画布仅保存背景而不保存图形
我有一个画布,我正在显示一张来自媒体商店的图片作为背景,然后我在上面画画。我想保存背景+上面画的内容,但我只能保存背景,这对我来说是无用的。我在努力理解我做错了什么。我基本上是按照人们的建议做的,但没用 以下是我的代码: 编辑:这次我在这里上传了所有的代码Java 保存画布仅保存背景而不保存图形,java,android,view,android-canvas,Java,Android,View,Android Canvas,我有一个画布,我正在显示一张来自媒体商店的图片作为背景,然后我在上面画画。我想保存背景+上面画的内容,但我只能保存背景,这对我来说是无用的。我在努力理解我做错了什么。我基本上是按照人们的建议做的,但没用 以下是我的代码: 编辑:这次我在这里上传了所有的代码 import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; i
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.util.ArrayList;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.Display;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Toast;
public class CanvasDrawingActivity extends Activity {
private ArrayList<Path> _graphics = new ArrayList<Path>();
private Paint mPaint;
public static final int GET_FROM_GALLERY = 1;
public static final int IMAGE_CAPTURE = 0;
public static final int SELECT_IMAGE_FROM_DEVICE = 1;
public Bitmap myBitmap;
public int isFirstTime = 0;
public DrawingPanel mPanel;
static int id = 1;
public Uri fileUri ;
@Override
public void onCreate(Bundle savedInstanceState) {
mPanel = new DrawingPanel(this);
mPanel.setId(findId());
super.onCreate(savedInstanceState);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//https://stackoverflow.com/questions/10937659/android-image-doesnt-save-using-native-camera-app-on-nexus-s
File f = new File(Environment.getExternalStorageDirectory().getPath(), String.format("%d.jpg", System.currentTimeMillis()));
fileUri= Uri.fromFile(f);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, IMAGE_CAPTURE);
setContentView(R.layout.main);
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.save:
savePicture();
return true;
case R.id.clear:
// startActivity(new Intent(this, Clear.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void savePicture(){
long now = System.currentTimeMillis();
OutputStream fos;
try {
fos = new FileOutputStream(String.format(Environment.getExternalStorageDirectory().getAbsolutePath()+"/edited_%d.jpg",now));
myBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finish(); //close the activity.
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//Detects request codes
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == IMAGE_CAPTURE && resultCode == RESULT_OK) {
Uri result;
result = fileUri;
//refresh storage
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
try {
myBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), result);
startDrawing();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if (resultCode == Activity.RESULT_CANCELED){
}
}
public void startDrawing(){
setContentView(mPanel);
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(0xFFFFFF00);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
}
public int findId(){
View v = findViewById(id);
while (v != null){
v = findViewById(++id);
}
return id++;
}
class DrawingPanel extends SurfaceView implements SurfaceHolder.Callback {
private DrawingThread _thread;
private Path path;
public DrawingPanel(Context context) {
super(context);
setDrawingCacheEnabled(true);
getHolder().addCallback(this);
_thread = new DrawingThread(getHolder(), this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (_thread.getSurfaceHolder()) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
path = new Path();
path.moveTo(event.getX(), event.getY());
path.lineTo(event.getX(), event.getY());
}else if(event.getAction() == MotionEvent.ACTION_MOVE){
path.lineTo(event.getX(), event.getY());
if(_graphics.size() > 0) {
_graphics.remove(_graphics.size() - 1);
}
_graphics.add(path);
}else if(event.getAction() == MotionEvent.ACTION_UP){
path.lineTo(event.getX(), event.getY());
_graphics.remove(_graphics.size() - 1);
_graphics.add(path);
}
return true;
}
}
//Source: http://thinkandroid.wordpress.com/2009/12/25/resizing-a-bitmap/
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
/**
* Converts a immutable bitmap to a mutable bitmap. This operation doesn't allocates
* more memory that there is already allocated.
*
* @param imgIn - Source image. It will be released, and should not be used more
* @return a copy of imgIn, but muttable.
*/
public Bitmap convertToMutable(Bitmap imgIn) {
try {
//this is the file going to use temporally to save the bytes.
// This file will not be a image, it will store the raw image data.
File file = new File(Environment.getExternalStorageDirectory() + File.separator + "temp.tmp");
//Open an RandomAccessFile
//Make sure you have added uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
//into AndroidManifest.xml file
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
// get the width and height of the source bitmap.
int width = imgIn.getWidth();
int height = imgIn.getHeight();
Config type = imgIn.getConfig();
//Copy the byte to the file
//Assume source bitmap loaded using options.inPreferredConfig = Config.ARGB_8888;
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer map = channel.map(MapMode.READ_WRITE, 0, imgIn.getRowBytes()*height);
imgIn.copyPixelsToBuffer(map);
//recycle the source bitmap, this will be no longer used.
imgIn.recycle();
System.gc();// try to force the bytes from the imgIn to be released
//Create a new bitmap to load the bitmap again. Probably the memory will be available.
imgIn = Bitmap.createBitmap(width, height, type);
map.position(0);
//load it back from temporary
imgIn.copyPixelsFromBuffer(map);
//close the temporary file and channel , then delete that also
channel.close();
randomAccessFile.close();
// delete the temp file
file.delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return imgIn;
}
@Override
public void onDraw(Canvas canvas) {
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
myBitmap = getResizedBitmap(myBitmap, height, width);
if (isFirstTime<3){
myBitmap = convertToMutable(myBitmap);
canvas.drawBitmap(myBitmap, 0, 0, null);
isFirstTime++;
}
for (Path path : _graphics) {
//canvas.drawPoint(graphic.x, graphic.y, mPaint);
canvas.drawPath(path, mPaint);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
_thread.setRunning(true);
_thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
class DrawingThread extends Thread {
private SurfaceHolder _surfaceHolder;
private DrawingPanel _panel;
private boolean _run = false;
public DrawingThread(SurfaceHolder surfaceHolder, DrawingPanel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
public SurfaceHolder getSurfaceHolder() {
return _surfaceHolder;
}
@Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
if (c!=null)
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
导入java.io.File;
导入java.io.FileNotFoundException;
导入java.io.FileOutputStream;
导入java.io.IOException;
导入java.io.OutputStream;
导入java.io.RandomAccessFile;
导入java.nio.MappedByteBuffer;
导入java.nio.channels.FileChannel;
导入java.nio.channels.FileChannel.MapMode;
导入java.util.ArrayList;
导入android.app.Activity;
导入android.app.AlertDialog;
导入android.content.Context;
导入android.content.DialogInterface;
导入android.content.Intent;
导入android.graphics.Bitmap;
导入android.graphics.Bitmap.Config;
导入android.graphics.BitmapFactory;
导入android.graphics.Canvas;
导入android.graphics.Matrix;
导入android.graphics.Paint;
导入android.graphics.Path;
导入android.net.Uri;
导入android.os.AsyncTask;
导入android.os.Bundle;
导入android.os.Environment;
导入android.os.Handler;
导入android.os.Message;
导入android.provider.MediaStore;
导入android.view.Display;
导入android.view.Menu;
导入android.view.MenuInflater;
导入android.view.MenuItem;
导入android.view.MotionEvent;
导入android.view.SurfaceHolder;
导入android.view.SurfaceView;
导入android.view.view;
导入android.widget.Toast;
公共课拉票活动扩展活动{
private ArrayList_graphics=new ArrayList();
私人油漆;
公共静态最终int GET_FROM_GALLERY=1;
公共静态最终整数图像_捕获=0;
公共静态最终整数从设备中选择图像=1;
公共位图;
public int isFirstTime=0;
公共绘图面板;
静态int-id=1;
公共Uri文件Uri;
@凌驾
创建时的公共void(Bundle savedInstanceState){
mPanel=新绘图面板(本);
mPanel.setId(findId());
super.onCreate(savedInstanceState);
意向意向=新意向(MediaStore.ACTION\u IMAGE\u CAPTURE);
//https://stackoverflow.com/questions/10937659/android-image-doesnt-save-using-native-camera-app-on-nexus-s
文件f=新文件(Environment.getExternalStorageDirectory().getPath(),String.format(“%d.jpg”,System.currentTimeMillis());
fileUri=Uri.fromFile(f);
intent.putExtra(MediaStore.EXTRA_输出,fileUri);
startActivityForResult(意图、图像捕获);
setContentView(R.layout.main);
}
公共布尔onCreateOptions菜单(菜单){
MenuInflater充气机=getMenuInflater();
充气机。充气(右菜单,菜单);
返回true;
}
公共布尔值onOptionsItemSelected(菜单项项){
开关(item.getItemId()){
案例R.id.save:
保存图片();
返回true;
案例R.id.clear:
//startActivity(新意图(这个,Clear.class));
返回true;
违约:
返回super.onOptionsItemSelected(项目);
}
}
公共图片(){
long now=System.currentTimeMillis();
输出流;
试一试{
fos=新文件输出流(String.format(Environment.getExternalStorageDirectory().getAbsolutePath()+“/edited_%d.jpg”,现在));
myBitmap.compress(Bitmap.CompressFormat.JPEG,100,fos);
}catch(filenotfounde异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
finish();//关闭活动。
}
@凌驾
ActivityResult上的公共void(int请求代码、int结果代码、意图数据){
//检测请求代码
super.onActivityResult(请求代码、结果代码、数据);
if(requestCode==IMAGE\u CAPTURE&&resultCode==RESULT\u OK){
Uri结果;
结果=fileUri;
//刷新存储
sendBroadcast(新的Intent(Intent.ACTION\u MEDIA\u挂载,Uri.parse(“文件:/”+Environment.getExternalStorageDirectory()));
试一试{
myBitmap=MediaStore.Images.Media.getBitmap(this.getContentResolver(),result);
startDrawing();
}catch(filenotfounde异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
else if(resultCode==Activity.RESULT\u已取消){
}
}
公共无效开始绘图(){
setContentView(mPanel);
mPaint=新油漆();
mPaint.setDither(true);
mPaint.setColor(0xFFFFFF00);
mPaint.setStyle(油漆、样式、笔划);
mPaint.setStrokeJoin(油漆.连接.圆形);
mPaint.setStrokeCap(油漆盖圆形);
mPaint.设定行程宽度(3);
}
public int findId(){
视图v=findViewById(id);
而(v!=null){
v=findViewById(++id);
}
返回id++;
}
类DrawingPanel扩展SurfaceView实现SurfaceHolder.Callback{
私有DrawingThread\u线程;
专用路径;
公共绘图面板(上下文){
超级(上下文);
setDrawingCacheEnabled(真);
getHolder().addCallback(此);
_thread=newdrawingthread(getHolder(),this);
}
@凌驾
公共布尔onTouchEvent(运动事件){
已同步(\u thread.getSurfaceHolder()){
if(event.getAction()==MotionEvent.ACTION\u向下){
路径=新路径();
moveTo(event.getX(),event.getY());
lineTo(event.getX(),event.getY());
}else if(event.getAction()==MotionEvent.ACTION\u MOVE){
lineTo(event.getX(),event.getY());
如果(_graphics.size()>0){
_graphics.remove(_graphics.size()-1);
}
_添加(路径);
}else if(event.ge
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="@+id/main_view">
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/save"
android:title="Save"/>
<item
android:id="@+id/clear"
android:title="Clear"/>
</menu>
@Override
public void onCreate(Bundle savedInstanceState) {
mPanel = new DrawingPanel(this);
mPanel.setId(findId());
super.onCreate(savedInstanceState);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
//https://stackoverflow.com/questions/10937659/android-image-doesnt-save-using-native-camera-app-on-nexus-s
File f = new File(Environment.getExternalStorageDirectory().getPath(), String.format("%d.jpg", System.currentTimeMillis()));
fileUri= Uri.fromFile(f);
intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
startActivityForResult(intent, IMAGE_CAPTURE);
setContentView(R.layout.main);
}
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
return true;
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.save:
savePicture();
return true;
case R.id.clear:
// startActivity(new Intent(this, Clear.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void savePicture(){
long now = System.currentTimeMillis();
OutputStream fos;
try {
//SAVE THIS ONE- replicate all paths
Canvas canvas = new Canvas(myBitmap);
for (Path path : _graphicsToSave)
{
canvas.drawPath(path, mPaint);
}
fos = new FileOutputStream(String.format(Environment.getExternalStorageDirectory().getAbsolutePath()+"/edited_%d.jpg",now));
myBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finish(); //close the activity.
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
//Detects request codes
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == IMAGE_CAPTURE && resultCode == RESULT_OK) {
Uri result;
result = fileUri;
//refresh storage
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
try {
myBitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), result);
//resize the picture to match the screen size
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
myBitmap = getResizedBitmap(myBitmap, height, width);
startDrawing();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else if (resultCode == Activity.RESULT_CANCELED){
}
}
//Source: http://thinkandroid.wordpress.com/2009/12/25/resizing-a-bitmap/
public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// create a matrix for the manipulation
Matrix matrix = new Matrix();
// resize the bit map
matrix.postScale(scaleWidth, scaleHeight);
// recreate the new Bitmap
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
}
public void startDrawing(){
setContentView(mPanel);
mPaint = new Paint();
mPaint.setDither(true);
mPaint.setColor(0xFFFFFF00);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
}
public int findId(){
View v = findViewById(id);
while (v != null){
v = findViewById(++id);
}
return id++;
}
class DrawingPanel extends SurfaceView implements SurfaceHolder.Callback {
private DrawingThread _thread;
private Path path;
public DrawingPanel(Context context) {
super(context);
setDrawingCacheEnabled(true);
getHolder().addCallback(this);
_thread = new DrawingThread(getHolder(), this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (_thread.getSurfaceHolder()) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
path = new Path();
path.moveTo(event.getX(), event.getY());
path.lineTo(event.getX(), event.getY());
}else if(event.getAction() == MotionEvent.ACTION_MOVE){
path.lineTo(event.getX(), event.getY());
if(_graphics.size() > 0) {
_graphics.remove(_graphics.size() - 1);
}
_graphics.add(path);
}else if(event.getAction() == MotionEvent.ACTION_UP){
path.lineTo(event.getX(), event.getY());
_graphics.remove(_graphics.size() - 1);
_graphics.add(path);
_graphicsToSave.add(path);
}
return true;
}
}
@Override
public void onDraw(Canvas canvas) {
if (isFirstTime<3){
canvas.drawBitmap(myBitmap, 0, 0, null);
isFirstTime++;
}
for (Path path : _graphics) {
canvas.drawPath(path, mPaint);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
_thread.setRunning(true);
_thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
class DrawingThread extends Thread {
private SurfaceHolder _surfaceHolder;
private DrawingPanel _panel;
private boolean _run = false;
public DrawingThread(SurfaceHolder surfaceHolder, DrawingPanel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
public SurfaceHolder getSurfaceHolder() {
return _surfaceHolder;
}
@Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
if (c!=null)
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
View mView;
mView.setDrawingCacheEnabled(true);
Bitmap newimg = mView.getDrawingCache();