2

メディアストアの画像を背景として表示しているキャンバスがあり、その上に描画しています。背景とその上に描かれたものを保存したいのですが、背景しか保存できず、役に立ちません。私は自分が間違っていることを理解しようとしています。私は基本的にここで人々が提案することをしましたが、役に立ちませんでした。

ここに私が持っているコードがあります: 編集: 今回はすべてのコードをここにアップロードしました

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);
                }
            }
        }
    }
}

}

これはmain.xmlです

<?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>

および menu.xml:

<?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);
                }
            }
        }
    }
}

}

4

2 に答える 2

0

何かを描画するには、4 つの基本コンポーネントが必要です。ピクセルを保持するビットマップ、描画呼び出しをホストするキャンバス (ビットマップへの書き込み)、描画プリミティブ (Rect、パス、テキスト、ビットマップなど)、およびペイント (図面の色とスタイルを説明します)。

現在貼り付けられているコード コードは、myBitmap を保存していることを示していますが、myBitmap を描画用のビットマップとして設定しているかどうかは示していません。完全なコードではない可能性があります。
この問題について考えられる唯一の理由は、保存しているビットマップに描画していないことです。これは、フィンガー ペイント用に作成したコードへのリンクです。このコードを参照して、キャンバスにビットマップが提供される方法と、ビットマップにパスが描画される方法を確認できます。

于 2012-09-21T19:47:40.383 に答える
0
View mView;
mView.setDrawingCacheEnabled(true);

Bitmap newimg = mView.getDrawingCache();

ビットマップを取得して、そのビットマップを保存してみてください。さらにサポートが必要であることをお知らせください

于 2012-09-21T07:20:58.853 に答える