表面视图拍照

surfaceview take photo

我有一个SurfaceView。必须将 SurfaceView 上的任何内容转换为 Bitmap。我搜索了很多资源。但是,我必须保留SurfaceView用于二维码筛选。也就是说,我不能用TextureView代替SurfaceView。我需要尽快解决这个问题。谢谢。 (我不介意使用任何现有的库)

要使用自定义相机拍摄图像,请使用以下代码,您实际上并不需要表面视图

相机预览:

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private android.hardware.Camera mCamera;
Boolean isPreviewRunning = true;

public void startFaceDetection(){
    android.hardware.Camera.Parameters params = mCamera.getParameters();

    if (params.getMaxNumDetectedFaces() > 0){
        mCamera.startFaceDetection();
    }
}

public CameraPreview(Context context, android.hardware.Camera camera) {
    super(context);
    mCamera = camera;
    mHolder = getHolder();
    mHolder.addCallback(this);
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void surfaceCreated(SurfaceHolder holder) {
    try {
        mCamera.setPreviewDisplay(holder);
        mCamera.startPreview();

        startFaceDetection();
    } catch (IOException e) {
        Log.d("error", "Error setting camera preview: " + e.getMessage());
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
}

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

    if (mHolder.getSurface() == null){
        return;
    }
    try {
        mCamera.stopPreview();
    } catch (Exception e){
        // ignore: tried to stop a non-existent preview
    }



    if (isPreviewRunning)
    {
        mCamera.stopPreview();
    }

    Camera.Parameters parameters = mCamera.getParameters();
    Display display = ((WindowManager) getContext().getSystemService(WINDOW_SERVICE)).getDefaultDisplay();


    if(display.getRotation() == Surface.ROTATION_0)
    {
        parameters.setPreviewSize(height, width);
        mCamera.setDisplayOrientation(90);
    }

    if(display.getRotation() == Surface.ROTATION_90)
    {
        parameters.setPreviewSize(width, height);
    }

    if(display.getRotation() == Surface.ROTATION_180)
    {
        parameters.setPreviewSize(height, width);
    }

    if(display.getRotation() == Surface.ROTATION_270)
    {
        parameters.setPreviewSize(width, height);
        mCamera.setDisplayOrientation(180);
    }

    try {
        mCamera.setPreviewDisplay(mHolder);
        previewCamera();

    } catch (Exception e){
        Log.d("error", "Error starting camera preview: " + e.getMessage());
    }

}

public void previewCamera()
{
    try
    {
        mCamera.setPreviewDisplay(mHolder);
        mCamera.startPreview();
        startFaceDetection();
        isPreviewRunning = true;
    }
    catch(Exception e)
    {
        Log.d("preview", "Cannot start preview", e);
    }
}}

相机Activityclass:

public class FrontBackCamera extends AppCompatActivity implements View.OnClickListener{

private android.hardware.Camera mCamera;
private CameraPreview mPreview;
FrameLayout preview;
RelativeLayout effect_set;
ImageView button_capture,change_camera,imagePreview,video_camera,effect_none,effect_mono,effect_negative,effect_sepia,
        effect_posterize,effect_whiteboard,effect_blackboard,effect_aqua,flash_state_true,flash_state_false;
CardView button_gallery;
Boolean self_cam = true;
MediaPlayer mediaPlayer = new MediaPlayer();
String mCurrentPhotoPath;
CustomTextView current_zoom_level;
SeekBar camera_seek;
String[] effects = new String[]{
        "EFFECT_NONE",
        "EFFECT_MONO",
        "EFFECT_NEGATIVE",
        "EFFECT_SOLARIZE",
        "EFFECT_SEPIA",
        "EFFECT_POSTERIZE",
        "EFFECT_WHITEBOARD",
        "EFFECT_BLACKBOARD",
        "EFFECT_AQUA"
};

String[] scenes = new String[]{
        "SCENE_MODE_ACTION",
        "SCENE_MODE_AUTO",
        "SCENE_MODE_BARCODE",
        "SCENE_MODE_BEACH",
        "SCENE_MODE_CANDLELIGHT",
        "SCENE_MODE_FIREWORKS",
        "SCENE_MODE_HDR",
        "SCENE_MODE_LANDSCAPE",
        "SCENE_MODE_NIGHT",
        "SCENE_MODE_NIGHT_PORTRAIT",
        "SCENE_MODE_PARTY",
        "SCENE_MODE_PORTRAIT",
        "SCENE_MODE_SNOW",
        "SCENE_MODE_SPORTS",
        "SCENE_MODE_STEADYPHOTO",
        "SCENE_MODE_SUNSET",
        "SCENE_MODE_THEATRE"
};

HorizontalScrollView effects_slider;
Boolean effect_state = true;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera_instance);

    setStatusbarTransperent();

    video_camera = (ImageView) findViewById(R.id.video_camera);
    effects_slider = (HorizontalScrollView) findViewById(R.id.effects_slider);
    effect_none = (ImageView) findViewById(R.id.effect_none);
    effect_mono = (ImageView) findViewById(R.id.effect_mono);
    effect_negative = (ImageView) findViewById(R.id.effect_negative);
    effect_sepia = (ImageView) findViewById(R.id.effect_sepia);
    effect_posterize = (ImageView) findViewById(R.id.effect_posterize);
    effect_whiteboard = (ImageView) findViewById(R.id.effect_whiteboard);
    effect_blackboard = (ImageView) findViewById(R.id.effect_blackboard);
    effect_aqua = (ImageView) findViewById(R.id.effect_aqua);
    flash_state_true = (ImageView) findViewById(R.id.flash_state_true);
    flash_state_false = (ImageView) findViewById(R.id.flash_state_false);

    effect_set = (RelativeLayout) findViewById(R.id.effect_set);

    preview = (FrameLayout) findViewById(R.id.camera_preview);
    button_capture = (ImageView) findViewById(R.id.button_capture);
    button_gallery = (CardView) findViewById(R.id.button_gallery);
    change_camera = (ImageView) findViewById(R.id.change_camera);
    camera_seek = (SeekBar) findViewById(R.id.camera_seek);
    current_zoom_level = (CustomTextView) findViewById(R.id.current_zoom_level);
    imagePreview = (ImageView) findViewById(R.id.imagePreview);

    if (CommonUtil.getImagePath(FrontBackCamera.this) != null) {
        imagePreview.setImageBitmap(BitmapFactory.decodeFile(CommonUtil.getImagePath(FrontBackCamera.this)));
    }

    mCamera = getCameraInstance(0);
    mPreview = new CameraPreview(this, mCamera);
    preview.addView(mPreview);

    video_camera.setOnClickListener(this);
    effect_set.setOnClickListener(this);
    flash_state_true.setOnClickListener(this);
    flash_state_false.setOnClickListener(this);
    effect_none.setOnClickListener(this);
    effect_mono.setOnClickListener(this);
    effect_negative.setOnClickListener(this);
    effect_sepia.setOnClickListener(this);
    effect_posterize.setOnClickListener(this);
    effect_whiteboard.setOnClickListener(this);
    effect_blackboard.setOnClickListener(this);
    effect_aqua.setOnClickListener(this);
    button_gallery.setOnClickListener(this);
    change_camera.setOnClickListener(this);
    button_capture.setOnClickListener(this);

    mCamera.setFaceDetectionListener(new MyFaceDetectionListener());
    camera_seek.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                                      boolean fromUser) {
            current_zoom_level.setText(String.valueOf(progress));
            zoom(progress + 1);
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
        }
    });


    if (CommonUtil.getFlashState(FrontBackCamera.this)){
        flash_state_true.setVisibility(View.VISIBLE);
        flash_state_false.setVisibility(View.GONE);
    }else {
        flash_state_true.setVisibility(View.GONE);
        flash_state_false.setVisibility(View.VISIBLE);
    }


}

public void setFlashOnOff(Boolean state){
    Log.d("method_cam",String.valueOf(state));
    if (state){
        Camera.Parameters param = mCamera.getParameters();
        param.setFlashMode(Camera.Parameters.FLASH_MODE_ON);
        mCamera.setParameters(param);
        flash_state_true.setVisibility(View.VISIBLE);
        flash_state_false.setVisibility(View.GONE);
    }else {
        Camera.Parameters param = mCamera.getParameters();
        param.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
        mCamera.setParameters(param);
        flash_state_true.setVisibility(View.GONE);
        flash_state_false.setVisibility(View.VISIBLE);
    }
}

public void setColorEffect(String effect){
    Camera.Parameters parameters = mCamera.getParameters();
    switch (effect) {
        case "EFFECT_NONE":
            parameters.setColorEffect(Camera.Parameters.EFFECT_NONE);
            break;
        case "EFFECT_MONO":
            parameters.setColorEffect(Camera.Parameters.EFFECT_MONO);
            break;
        case "EFFECT_NEGATIVE":
            parameters.setColorEffect(Camera.Parameters.EFFECT_NEGATIVE);
            break;
        case "EFFECT_SEPIA":
            parameters.setColorEffect(Camera.Parameters.EFFECT_SEPIA);
            break;
        case "EFFECT_POSTERIZE":
            parameters.setColorEffect(Camera.Parameters.EFFECT_POSTERIZE);
            break;
        case "EFFECT_WHITEBOARD":
            parameters.setColorEffect(Camera.Parameters.EFFECT_WHITEBOARD);
            break;
        case "EFFECT_BLACKBOARD":
            parameters.setColorEffect(Camera.Parameters.EFFECT_BLACKBOARD);
            break;
        case "EFFECT_AQUA":
            parameters.setColorEffect(Camera.Parameters.EFFECT_AQUA);
            break;
    }
    mCamera.setParameters(parameters);
}


public void zoom(int zoomValue)
{
    Camera.Parameters params=mCamera.getParameters();
    params.setZoom(zoomValue);
    mCamera.setParameters(params);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public void setStatusbarTransperent(){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Window window = this.getWindow();
        window.getDecorView().setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
        window.setStatusBarColor(Color.TRANSPARENT);
    }
}


public static android.hardware.Camera getCameraInstance(int camera_id){
    android.hardware.Camera c = null;
    try {
        // change the value for selfie -> 1
        c = android.hardware.Camera.open(camera_id);
    }
    catch (Exception e){
        // Camera is not available (in use or does not exist)
    }
    return c;
}

private android.hardware.Camera.PictureCallback mPicture = new android.hardware.Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, android.hardware.Camera camera) {

        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),"Camera");
        try {
            File pictureFile = File.createTempFile(
                    imageFileName,  /* prefix */
                    ".jpg",         /* suffix */
                    storageDir      /* directory */
            );

            ExifInterface exifInterface = new ExifInterface(pictureFile.getAbsolutePath());
            exifInterface.getAttribute(ExifInterface.TAG_ORIENTATION);

            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.close();

            mCurrentPhotoPath = pictureFile.getAbsolutePath();

            CommonUtil.setImagePath(mCurrentPhotoPath,FrontBackCamera.this);

            imagePreview.setImageBitmap(BitmapFactory.decodeFile(mCurrentPhotoPath));

            preview.removeAllViews();
            preview.addView(mPreview);

        } catch (FileNotFoundException e) {
            Log.d("File", "not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d("error", "Error accessing file: " + e.getMessage());
        }
    }
};

@Override
public void onClick(View view) {
    switch (view.getId()){
        case R.id.button_gallery:
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://media/internal/images/media"));
            startActivity(intent);
            break;
        case R.id.button_capture:
            try {

               new MediaActionSound().play(MediaActionSound.SHUTTER_CLICK);
            } catch (Exception e) {
                e.printStackTrace();
            }
            mCamera.takePicture(null, null, mPicture);
            CommonUtil.setImagePath(mCurrentPhotoPath,FrontBackCamera.this);
            break;
        case R.id.change_camera:
            mCamera.release();
            decideCameraFacing();
            break;
        case R.id.video_camera:
            mCamera.release();
            startActivity(new Intent(FrontBackCamera.this,RearVideoCamera.class));
            break;
        case R.id.effect_none:
            setColorEffect(effects[0]);
            break;
        case R.id.effect_mono:
            setColorEffect(effects[1]);
            break;
        case R.id.effect_negative:
            setColorEffect(effects[2]);
            break;
        case R.id.effect_sepia:
            setColorEffect(effects[4]);
            break;
        case R.id.effect_posterize:
            setColorEffect(effects[5]);
            break;
        case R.id.effect_whiteboard:
            setColorEffect(effects[6]);
            break;
        case R.id.effect_blackboard:
            setColorEffect(effects[7]);
            break;
        case R.id.effect_aqua:
            setColorEffect(effects[8]);
            break;
        case R.id.flash_state_true:
            CommonUtil.setFlashState(false,FrontBackCamera.this);
            setFlashOnOff(false);
            break;
        case R.id.flash_state_false:
            CommonUtil.setFlashState(true,FrontBackCamera.this);
            setFlashOnOff(true);
            break;
        case R.id.effect_set:
            if (effect_state){
                effects_slider.setVisibility(View.VISIBLE);
                effect_state = false;
            }else {
                effects_slider.setVisibility(View.GONE);
                effect_state = true;
            }
            break;
    }
}


public void decideCameraFacing(){
    if (self_cam){
        self_cam = false;
        preview.removeAllViews();
        mCamera = getCameraInstance(1);
        mPreview = new CameraPreview(this, mCamera);
        preview.addView(mPreview);
        change_camera.setImageDrawable(getDrawable(R.drawable.camera_rear));


    }else {
        preview.removeAllViews();
        mCamera = getCameraInstance(0);
        mPreview = new CameraPreview(this, mCamera);
        preview.addView(mPreview);
        change_camera.setImageDrawable(getDrawable(R.drawable.camera_front));
        self_cam = true;

    }
}

@Override
public void onBackPressed() {
    super.onBackPressed();
    mCamera.release();
    this.finish();
}


class MyFaceDetectionListener implements Camera.FaceDetectionListener {

    @Override
    public void onFaceDetection(Camera.Face[] faces, Camera camera) {
        if (faces.length > 0){
            Log.d("FaceDetection", "face detected: "+ faces.length +
                    " Face 1 Location X: " + faces[0].rect.centerX() +
                    "Y: " + faces[0].rect.centerY() );
        }
    }
}}

Xml 对于 activity class

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<FrameLayout
    android:id="@+id/camera_preview"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


<RelativeLayout
    android:id="@+id/action_layout"
    android:layout_width="match_parent"
    android:layout_height="@dimen/margin_80"
    android:layout_alignParentBottom="true"
    android:background="@color/transparent_background">


    <android.support.v7.widget.CardView
        android:id="@+id/button_gallery"
        android:layout_width="@dimen/margin_40"
        android:layout_height="@dimen/margin_40"
        android:layout_alignParentStart="true"
        android:layout_centerVertical="true"
        android:layout_marginStart="@dimen/margin_40"
        app:cardCornerRadius="@dimen/margin_10">

        <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_margin="@dimen/margin_1"
            app:cardCornerRadius="@dimen/margin_10">

            <ImageView
                android:id="@+id/imagePreview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitXY" />
        </android.support.v7.widget.CardView>

    </android.support.v7.widget.CardView>


    <ImageView
        android:id="@+id/button_capture"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_centerInParent="true"
        android:layout_gravity="center"
        android:src="@drawable/camera_icon" />


    <ImageView
        android:id="@+id/change_camera"
        android:layout_width="@dimen/margin_30"
        android:layout_height="@dimen/margin_30"
        android:layout_alignParentEnd="true"
        android:layout_centerVertical="true"
        android:layout_gravity="center"
        android:layout_marginEnd="@dimen/margin_40"
        android:src="@drawable/camera_front" />

</RelativeLayout>



<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentEnd="true"
    android:layout_centerVertical="true"
    android:layout_marginEnd="@dimen/margin_15"
    android:orientation="vertical">


    <LinearLayout
        android:id="@+id/seek_expose"
        android:layout_width="@dimen/margin_32"
        android:layout_height="@dimen/margin_200"
        android:orientation="vertical">

        <com.mycamera.view.CustomTextView
            android:id="@+id/current_zoom_level"
            android:layout_width="@dimen/margin_32"
            android:layout_height="@dimen/margin_20"
            android:gravity="center"
            android:text="@string/zero"
            android:textColor="@android:color/white"
            android:textSize="@dimen/text_16"
            app:font="@string/avenir_book" />

        <FrameLayout
            android:layout_width="@dimen/margin_32"
            android:layout_height="@dimen/margin_180"
            android:orientation="vertical">

            <SeekBar
                android:id="@+id/camera_seek"
                android:layout_width="@dimen/margin_180"
                android:layout_height="@dimen/margin_25"
                android:layout_gravity="center"
                android:max="5"
                android:progressDrawable="@drawable/seekbar_track"
                android:rotation="270"
                android:splitTrack="false"
                android:thumb="@drawable/seekbar_thumb" />

        </FrameLayout>


    </LinearLayout>


    <LinearLayout
        android:layout_width="@dimen/margin_32"
        android:layout_gravity="center"
        android:paddingBottom="@dimen/margin_20"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/flash_state_true"
            android:layout_width="@dimen/margin_32"
            android:layout_height="@dimen/margin_30"
            android:layout_gravity="center"
            android:layout_marginStart="@dimen/margin_1"
            android:layout_marginTop="@dimen/margin_12"
            android:src="@drawable/flash_on"
            android:visibility="gone" />

        <ImageView
            android:id="@+id/flash_state_false"
            android:layout_width="@dimen/margin_32"
            android:layout_height="@dimen/margin_30"
            android:layout_gravity="center"
            android:layout_marginStart="@dimen/margin_1"
            android:layout_marginTop="@dimen/margin_12"
            android:src="@drawable/flash_off" />


        <RelativeLayout
            android:id="@+id/effect_set"
            android:layout_width="@dimen/margin_32"
            android:layout_height="@dimen/margin_35"
            android:layout_marginTop="@dimen/margin_12"
            android:background="@drawable/swipe_left_image_card_background">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:padding="@dimen/margin_3"
                android:src="@drawable/effect_icon" />
        </RelativeLayout>

        <ImageView
            android:id="@+id/video_camera"
            android:layout_width="@dimen/margin_32"
            android:layout_height="@dimen/margin_30"
            android:layout_gravity="center"
            android:layout_marginStart="@dimen/margin_1"
            android:layout_marginTop="@dimen/margin_12"
            android:src="@drawable/ic_videocam" />

    </LinearLayout>
</LinearLayout>

<HorizontalScrollView
    android:id="@+id/effects_slider"
    android:layout_width="match_parent"
    android:layout_height="@dimen/margin_50"
    android:layout_above="@+id/action_layout"
    android:background="@color/transparent_background"
    android:scrollbars="none"
    android:visibility="gone">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="center_horizontal"
        android:layout_margin="@dimen/margin_5"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/effect_none"
            android:layout_width="@dimen/margin_40"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_3"
            android:src="@drawable/filter_none" />

        <ImageView
            android:id="@+id/effect_mono"
            android:layout_width="@dimen/margin_40"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_3"
            android:src="@drawable/filter_1" />

        <ImageView
            android:id="@+id/effect_negative"
            android:layout_width="@dimen/margin_40"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_3"
            android:src="@drawable/filter_2" />

        <ImageView
            android:id="@+id/effect_sepia"
            android:layout_width="@dimen/margin_40"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_3"
            android:src="@drawable/filter_4" />

        <ImageView
            android:id="@+id/effect_posterize"
            android:layout_width="@dimen/margin_40"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_3"
            android:src="@drawable/filter_5" />

        <ImageView
            android:id="@+id/effect_whiteboard"
            android:layout_width="@dimen/margin_40"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_3"
            android:src="@drawable/filter_6" />

        <ImageView
            android:id="@+id/effect_blackboard"
            android:layout_width="@dimen/margin_40"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_3"
            android:src="@drawable/filter_7" />

        <ImageView
            android:id="@+id/effect_aqua"
            android:layout_width="@dimen/margin_40"
            android:layout_height="match_parent"
            android:layout_marginStart="@dimen/margin_3"
            android:src="@drawable/filter_8" />
    </LinearLayout>
</HorizontalScrollView>

CommonUtil class

public class CommonUtil {

public static void setImagePath(String photoPath, Context context){
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    final SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.remove("picturePath");
    editor.putString("picturePath",photoPath);
    editor.apply();
}

public static String getImagePath(Context context){
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    return sharedPreferences.getString("picturePath",null);
}

public static void setFlashState(Boolean flash_state,Context context){
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putBoolean("flash_state",flash_state);
    editor.apply();
    Log.d("util_flashstate",String.valueOf(flash_state));
}

public static boolean getFlashState(Context context){
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    return sharedPreferences.getBoolean("flash_state",false);
}}