从customview获取Android截图(getDrawingCache())会返回黑色图像

时间:2016-11-01 08:25:44

标签: android screenshot android-custom-view

现在我正在尝试从自定义类中捕获位图图像,该类可以检测和跟踪面部。但它返回黑色图像。我认为问题是getDrawingCache()方法无法从自定义视图中获取截图图像。除了这个自定义视图,捕获其他视图进展顺利。

这是我使用的代码,

main.xml中

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/topLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/llCameraView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="0.1">

        <com.google.android.gms.samples.vision.face.facetracker.ui.camera.CameraSourcePreview
            android:id="@+id/preview"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <com.google.android.gms.samples.vision.face.facetracker.ui.camera.GraphicOverlay
                android:id="@+id/faceOverlay"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />


        </com.google.android.gms.samples.vision.face.facetracker.ui.camera.CameraSourcePreview>

    </LinearLayout>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:orientation="horizontal"
        android:background="#00ffffff">

        <ImageView
            android:id="@+id/ivChangeCamera"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/change_64_w"
            android:layout_margin="10dp"/>

        <ImageView
            android:id="@+id/ivTakePicture"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/takepic"
            android:layout_centerHorizontal="true"
            android:layout_margin="10dp"/>

        <ImageView
            android:id="@+id/ivFilter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/filter_64_w"
            android:layout_alignParentEnd="true"
            android:layout_alignParentRight="true"
            android:layout_margin="10dp"/>

        <ImageView
            android:id="@+id/ivSticker"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/sticker_64_w"
            android:layout_toLeftOf="@id/ivFilter"
            android:layout_margin="10dp"/>

    </RelativeLayout>

</LinearLayout>

MainActivity.java的一部分

    ImageView takePicture = (ImageView) findViewById(R.id.ivTakePicture);
    final LinearLayout llCameraView = (LinearLayout)findViewById(R.id.llCameraView);
    takePicture.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    ContextWrapper wrapper = new ContextWrapper(getApplicationContext());
                    File file = wrapper.getDir("Images", MODE_PRIVATE);
                    file = new File(file, "UniqueFileName"+".jpg");


                    llCameraView.buildDrawingCache();
                    Bitmap captureView;
                    llCameraView.setDrawingCacheEnabled(true);
                    captureView = Bitmap.createBitmap(llCameraView.getDrawingCache());
                    llCameraView.setDrawingCacheEnabled(false);    


                    try{
                        OutputStream stream = null;
                        stream = new FileOutputStream(file);
                        captureView.compress(Bitmap.CompressFormat.JPEG,100,stream);
                        stream.flush();
                        stream.close();
                        Toast.makeText(getApplicationContext(), "Captured!", Toast.LENGTH_LONG).show();
                    }catch (IOException e) // Catch the exception
                    {
                        e.printStackTrace();
                        Toast.makeText(getApplicationContext(), "Failed!", Toast.LENGTH_LONG).show();
                    }
                }
            }); 

GraphicOverlay.java

    public class GraphicOverlay extends View {
        private final Object mLock = new Object();
        private int mPreviewWidth;
        private float mWidthScaleFactor = 1.0f;
        private int mPreviewHeight;
        private float mHeightScaleFactor = 1.0f;
        private int mFacing = CameraSource.CAMERA_FACING_BACK;
        private Set<Graphic> mGraphics = new HashSet<>();


        public static abstract class Graphic {
            private GraphicOverlay mOverlay;

            public Graphic(GraphicOverlay overlay) {
                mOverlay = overlay;
            }


            public abstract void draw(Canvas canvas);


            public float scaleX(float horizontal) {
                return horizontal * mOverlay.mWidthScaleFactor;
            }


            public float scaleY(float vertical) {
                return vertical * mOverlay.mHeightScaleFactor;
            }


            public float translateX(float x) {
                if (mOverlay.mFacing == CameraSource.CAMERA_FACING_FRONT) {
                    return mOverlay.getWidth() - scaleX(x);
                } else {
                    return scaleX(x);
                }
            }


            public float translateY(float y) {
                return scaleY(y);
            }

            public void postInvalidate() {
                mOverlay.postInvalidate();
            }
        }

        public GraphicOverlay(Context context, AttributeSet attrs) {
            super(context, attrs);
        }


        public void clear() {
            synchronized (mLock) {
                mGraphics.clear();
            }
            postInvalidate();
        }


        public void add(Graphic graphic) {
            synchronized (mLock) {
                mGraphics.add(graphic);
            }
            postInvalidate();
        }


        public void remove(Graphic graphic) {
            synchronized (mLock) {
                mGraphics.remove(graphic);
            }
            postInvalidate();
        }


        public void setCameraInfo(int previewWidth, int previewHeight, int facing) {
            synchronized (mLock) {
                mPreviewWidth = previewWidth;
                mPreviewHeight = previewHeight;
                mFacing = facing;
            }
            postInvalidate();
        }


        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);

            synchronized (mLock) {
                if ((mPreviewWidth != 0) && (mPreviewHeight != 0)) {
                    mWidthScaleFactor = (float) canvas.getWidth() / (float) mPreviewWidth;
                    mHeightScaleFactor = (float) canvas.getHeight() / (float) mPreviewHeight;
                }

                for (Graphic graphic : mGraphics) {
                    graphic.draw(canvas);
                }
            }
        }

CameraSourcePreview.java

public class CameraSourcePreview extends ViewGroup {
private static final String TAG = "CameraSourcePreview";

private Context mContext;
private SurfaceView mSurfaceView;
private boolean mStartRequested;
private boolean mSurfaceAvailable;
private CameraSource mCameraSource;

private GraphicOverlay mOverlay;

public CameraSourcePreview(Context context, AttributeSet attrs) {
    super(context, attrs);
    mContext = context;
    mStartRequested = false;
    mSurfaceAvailable = false;

    mSurfaceView = new SurfaceView(context);
    mSurfaceView.getHolder().addCallback(new SurfaceCallback());
    addView(mSurfaceView);
}

public void start(CameraSource cameraSource) throws IOException {
    if (cameraSource == null) {
        stop();
    }

    mCameraSource = cameraSource;

    if (mCameraSource != null) {
        mStartRequested = true;
        startIfReady();
    }
}

public void start(CameraSource cameraSource, GraphicOverlay overlay) throws IOException {
    mOverlay = overlay;
    start(cameraSource);
}

public void stop() {
    if (mCameraSource != null) {
        mCameraSource.stop();
    }
}

public void release() {
    if (mCameraSource != null) {
        mCameraSource.release();
        mCameraSource = null;
    }
}

private void startIfReady() throws IOException {
    if (mStartRequested && mSurfaceAvailable) {
        mCameraSource.start(mSurfaceView.getHolder());
        if (mOverlay != null) {
            Size size = mCameraSource.getPreviewSize();
            int min = Math.min(size.getWidth(), size.getHeight());
            int max = Math.max(size.getWidth(), size.getHeight());
            if (isPortraitMode()) {
                // Swap width and height sizes when in portrait, since it will be rotated by
                // 90 degrees
                mOverlay.setCameraInfo(min, max, mCameraSource.getCameraFacing());
            } else {
                mOverlay.setCameraInfo(max, min, mCameraSource.getCameraFacing());
            }
            mOverlay.clear();
        }
        mStartRequested = false;
    }
}

private class SurfaceCallback implements SurfaceHolder.Callback {
    @Override
    public void surfaceCreated(SurfaceHolder surface) {
        mSurfaceAvailable = true;
        try {
            startIfReady();
        } catch (IOException e) {
            Log.e(TAG, "Could not start camera source.", e);
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surface) {
        mSurfaceAvailable = false;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }
}

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    int width = 320;
    int height = 240;
    if (mCameraSource != null) {
        Size size = mCameraSource.getPreviewSize();
        if (size != null) {
            width = size.getWidth();
            height = size.getHeight();
        }
    }

    // Swap width and height sizes when in portrait, since it will be rotated 90 degrees
    if (isPortraitMode()) {
        int tmp = width;
        width = height;
        height = tmp;
    }

    final int layoutWidth = right - left;
    final int layoutHeight = bottom - top;

  }

    for (int i = 0; i < getChildCount(); ++i) {
        getChildAt(i).layout(0, 0, layoutWidth, layoutHeight);
    }

    try {
        startIfReady();
    } catch (IOException e) {
        Log.e(TAG, "Could not start camera source.", e);
    }
}

private boolean isPortraitMode() {
    int orientation = mContext.getResources().getConfiguration().orientation;
    if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
        return false;
    }
    if (orientation == Configuration.ORIENTATION_PORTRAIT) {
        return true;
    }

    Log.d(TAG, "isPortraitMode returning false by default");
    return false;
}

}

1 个答案:

答案 0 :(得分:0)

我可以使用以下方法捕获图像:

mCameraSource.takePicture(null, CameraSource.PictureCallback { data ->
            file = File.createTempFile("name", ".jpg")
            file?.let {
                var os: OutputStream? = null
                try {
                    var bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
                    val bos = ByteArrayOutputStream()
                    bitmap.compress(Bitmap.CompressFormat.WEBP, 80, bos)
                    val bitmapData = bos.toByteArray()
                    val fos = FileOutputStream(file)
                    fos.write(bitmapData)
                    fos.flush()
                    fos.close()
                } catch (e: IOException) {
                    e.printStackTrace()
                } finally {
                    if (os != null) {
                        try {
                            os.close()
                        } catch (e: IOException) {
                            e.printStackTrace()
                        }
                    }
                }
            }
        })

使用压缩版本创建的临时文件。现在,您可以播放临时文件了。