相机在设备

时间:2018-01-28 12:19:05

标签: android performance image-processing android-camera image-compression

在我的项目中,我正在从相机中捕捉图像。我正在从应用程序中获取全尺寸图像(而不是使用缩略图)。捕获的图像尺寸非常大, 7到18 mb 。当我从默认相机应用程序拍摄图像时,尺寸大致仅 2.5 mb 。除了花费大量时间(6-10秒)加载并保存到文件夹之外。这种情况发生在我使用Android设备时,在模拟器上运行良好。这是我的代码:

package com.stegano.strenggeheim.fragment;

import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.stegano.strenggeheim.BuildConfig;
import com.stegano.strenggeheim.R;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;


public class FragmentEncode extends Fragment {
    private static final String MESSAGE_IMAGE_SAVED = "Image Saved!";;
    private static final String MESSAGE_FAILED = "Failed!";
    private static final String IMAGE_DIRECTORY = "/StrengGeheim";
    private static final int GALLERY = 0, CAMERA = 1;
    private File capturedImage;
    TextView imageTextMessage;
    ImageView loadImage;

    public FragmentEncode() {
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    private void galleryIntent() {
        Intent galleryIntent = new Intent(Intent.ACTION_PICK,
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        startActivityForResult(galleryIntent, GALLERY);
    }

    private void cameraIntent() {
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        Uri fileUri = getOutputMediaFileUri();
        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
        startActivityForResult(intent, CAMERA);
    }

    private Uri getOutputMediaFileUri() {
        try {
            capturedImage = getOutputMediaFile();
            return FileProvider.getUriForFile(getActivity(), BuildConfig.APPLICATION_ID + ".provider", capturedImage);
        }
        catch (IOException ex){
            ex.printStackTrace();
            Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
        }
        return null;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_encode, container, false);

        imageTextMessage = view.findViewById(R.id.imageTextMessage);
        loadImage =  view.findViewById(R.id.loadImage);

        loadImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                showPictureDialog();
            }
        });
        return view;
    }

    private void showPictureDialog(){
        AlertDialog.Builder pictureDialog = new AlertDialog.Builder(getContext());
        pictureDialog.setTitle("Select Action");
        String[] pictureDialogItems = {
                "Select photo from gallery",
                "Capture photo from camera",
                "Cancel"
        };
        pictureDialog.setItems(pictureDialogItems,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        switch (which) {
                            case 0:
                                galleryIntent();
                                break;
                            case 1:
                                cameraIntent();
                                break;
                            case 2:
                                dialog.dismiss();
                                break;
                        }
                    }
                });
        pictureDialog.show();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == getActivity().RESULT_CANCELED) {
            return;
        }
        try {
            if (requestCode == GALLERY && data != null) {
                    Bitmap bitmap = getBitmapFromData(data, getContext());
                    File mediaFile = getOutputMediaFile();
                    String path = saveImage(bitmap, mediaFile);
                    Log.println(Log.INFO, "Message", path);
                    Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
                    loadImage.setImageBitmap(bitmap);
                    imageTextMessage.setVisibility(View.INVISIBLE);

            } else if (requestCode == CAMERA) {
                    final Bitmap bitmap = BitmapFactory.decodeFile(capturedImage.getAbsolutePath());
                    loadImage.setImageBitmap(bitmap);
                     saveImage(bitmap, capturedImage);
                    Toast.makeText(getContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_SHORT).show();
                    imageTextMessage.setVisibility(View.INVISIBLE);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            Toast.makeText(getContext(), MESSAGE_FAILED, Toast.LENGTH_SHORT).show();
        }
    }

    private Bitmap getBitmapFromData(Intent intent, Context context){
        Uri selectedImage = intent.getData();
        String[] filePathColumn = { MediaStore.Images.Media.DATA };
        Cursor cursor = context.getContentResolver()
                .query(selectedImage,filePathColumn, null, null, null);
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        String picturePath = cursor.getString(columnIndex);
        cursor.close();
        return BitmapFactory.decodeFile(picturePath);
    }

    private String saveImage(Bitmap bmpImage, File mediaFile) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        bmpImage.compress(Bitmap.CompressFormat.PNG, 50, bytes);
        try {
            FileOutputStream fo = new FileOutputStream(mediaFile);
            fo.write(bytes.toByteArray());
            MediaScannerConnection.scanFile(getContext(),
                    new String[]{mediaFile.getPath()},
                    new String[]{"image/png"}, null);
            fo.close();

            return mediaFile.getAbsolutePath();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return "";
    }

    private File getOutputMediaFile() throws IOException {
        File encodeImageDirectory =
                new File(Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);

        if (!encodeImageDirectory.exists()) {
            encodeImageDirectory.mkdirs();
        }
        String uniqueId = UUID.randomUUID().toString();
        File mediaFile = new File(encodeImageDirectory, uniqueId + ".png");
        mediaFile.createNewFile();
        return mediaFile;
    }
}

2 个答案:

答案 0 :(得分:0)

您可以做的是在线下载可用的API,或者,如果需要,下载某些在线压缩器的源代码。然后你可以用它作为模型。永远不要直接使用源代码。跨语言广泛支持的是:https://optimus.keycdn.com/support/image-compression-api/

答案 1 :(得分:0)

我从相机拍摄图像并获取文件。所以,我将图像直接保存在我使用getOutputMediaFile()方法生成的文件位置。为此,我正在重载这样的saveImage()方法:

private void saveImage(File mediaImage) {
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    Uri contentUri = Uri.fromFile(mediaImage);
    mediaScanIntent.setData(contentUri);
    getContext().sendBroadcast(mediaScanIntent);
}

此方法会将图像放在所需的文件位置,并且还可以访问其他应用的图库。此方法与此Taking Photos Simply

上的galleryAddPic()方法相同

但是,如果从图库中选择照片,我将必须在所需位置创建文件,并将所选图像的字节写入该文件,因此旧版{{ 1}}方法不会改变。

saveImage()方法中,这是我使用重载onActivityResult方法的方式:

saveImage()