setDisplayOrientation摄像头做了错误的方向时,保存图像 [英] setDisplayOrientation in Camera make wrong orientation when save image

查看:2050
本文介绍了setDisplayOrientation摄像头做了错误的方向时,保存图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做Android中的OCR应用程序,并已安装OCR引擎,现在要创建相机Surfaceview并且对顶部的区域框来选择捕获区域。

I'm making an OCR app in Android and already installed OCR engine, and now want to create Surfaceview of Camera and have an area box on top to select capture area.

我满足surfaceview显示方向的问题:它旋转90度至左:

I meet the problem with Orientation of surfaceview display: it rotated 90 degree to left:

和我克服了

Camera.setDisplayOrientation(90)

和一套setDisplayOrientation后

不过,似乎是摄像头,当我捕捉图像的bug,它旋转90度到左。

But, seem to be the bug of camera when I capture image, it rotated 90 degree to left.

如果我不使用setDisplayOrientation功能,sufaceview是错误的方向显示(横向),但拍摄的图像是一样的方位显示。

If I don't use setDisplayOrientation function, the sufaceview is wrong orientation display (landscape) but captured image is same orientation with displayed.

所以,我认为,传感器的自然方向为横向,我没有把它调整为肖像,我只是迫使显示器人像,当我捕捉,图像有摄像头的真正方向:横向

So that, I think, natural orientation of sensor is landscape and I did not adjust it to portrait, I just force display to portrait and when I capture, image has real orientation of camera: landscape.

我不希望保存的图像和旋转它,因为规模和锐利的图像依赖于区域内的用户在surfaceview的顶部被选中。
任何机构可以暗示我什么来解决这个问题,或者给一个简短的文件/ TUT样?

I DON'T want to save image and rotate it, because the size and sharp of image depend on area user was selected on top of surfaceview. Any body can hint me anything to solve that problem, or give a short document/TUT about that?

推荐答案

试试这个类将处理所有的旋转和缩放任务,为您: -

Try this class it will handle all rotation and scaling task for you :-

package com.serveroverload.cube.controller;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Environment;
import android.util.Base64;
import android.util.Log;
import android.widget.Toast;

public class CamerHandler {

    private CamerHandler() {

        getAllImages();
    }

    private static CamerHandler camerHandler;

    public static CamerHandler GetCamerHandlerInstance() {
        if (null == camerHandler) {
            camerHandler = new CamerHandler();
        }
        return camerHandler;
    }

    private static final String CAM_DIRECTORY = "CamDirectory";
    private static final int MAX_HEIGHT = 1024;
    private static final int MAX_WIDTH = 1280;

    private ArrayList<File> imageURL = new ArrayList<File>();

    public ArrayList<File> getImageURL() {
        return imageURL;
    }

    public void setImageURL(ArrayList<File> imageURL) {
        this.imageURL = imageURL;
    }

    public void getAllImages() {

        imageURL.clear();

        File folder = new File(getImageDirectory());
        File[] listOfFiles = folder.listFiles();

        if (null != listOfFiles && listOfFiles.length != 0) {

            for (int i = 0; i < listOfFiles.length; i++) {
                if (listOfFiles[i].isFile()) {

                    imageURL.add(listOfFiles[i]);

                    System.out.println("File " + listOfFiles[i].getName());
                } else if (listOfFiles[i].isDirectory()) {
                    System.out.println("Directory " + listOfFiles[i].getName());
                }
            }
        }
    }

    /**
     * This method is responsible for solving the rotation issue if exist. Also
     * scale the images to 1024x1024 resolution
     *
     * @param context
     *            The current context
     * @param selectedImage
     *            The Image URI
     * @return Bitmap image results
     * @throws IOException
     */
    public Bitmap handleSamplingAndRotationBitmap(Context context,
            Uri selectedImage) throws IOException {

        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;

        InputStream imageStream = context.getContentResolver().openInputStream(
                selectedImage);
        BitmapFactory.decodeStream(imageStream, null, options);
        imageStream.close();

        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, MAX_WIDTH,
                MAX_HEIGHT);

        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        imageStream = context.getContentResolver().openInputStream(
                selectedImage);
        Bitmap img = BitmapFactory.decodeStream(imageStream, null, options);

        // img = rotateImageIfRequired(img, selectedImage);

        img = rotateBitmap(context, img, selectedImage);
        return img;
    }

    public Bitmap rotateBitmap(Context context, Bitmap bitmap, Uri selectedImage) {

        ExifInterface exif;
        try {
            exif = new ExifInterface(selectedImage.getPath());

            int orientation = exif.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_UNDEFINED);

            Matrix matrix = new Matrix();
            switch (orientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                return bitmap;
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                matrix.setScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                matrix.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                matrix.setRotate(180);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_TRANSPOSE:
                matrix.setRotate(90);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                matrix.setRotate(90);
                break;
            case ExifInterface.ORIENTATION_TRANSVERSE:
                matrix.setRotate(-90);
                matrix.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                matrix.setRotate(-90);
                break;
            default:
                return bitmap;
            }
            // try {
            Bitmap bmRotated = Bitmap.createBitmap(bitmap, 0, 0,
                    bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            bitmap.recycle();
            return bmRotated;

        } catch (IOException e) {

            e.printStackTrace();

            return null;
        } catch (OutOfMemoryError e) {
            e.printStackTrace();

            return null;
        }
    }

    /**
     * Calculate an inSampleSize for use in a {@link BitmapFactory.Options}
     * object when decoding bitmaps using the decode* methods from
     * {@link BitmapFactory}. This implementation calculates the closest
     * inSampleSize that will result in the final decoded bitmap having a width
     * and height equal to or larger than the requested width and height. This
     * implementation does not ensure a power of 2 is returned for inSampleSize
     * which can be faster when decoding but results in a larger bitmap which
     * isn't as useful for caching purposes.
     *
     * @param options
     *            An options object with out* params already populated (run
     *            through a decode* method with inJustDecodeBounds==true
     * @param reqWidth
     *            The requested width of the resulting bitmap
     * @param reqHeight
     *            The requested height of the resulting bitmap
     * @return The value to be used for inSampleSize
     */
    private int calculateInSampleSize(BitmapFactory.Options options,
            int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;

        if (height > reqHeight || width > reqWidth) {

            // Calculate ratios of height and width to requested height and
            // width
            final int heightRatio = Math.round((float) height
                    / (float) reqHeight);
            final int widthRatio = Math.round((float) width / (float) reqWidth);

            // Choose the smallest ratio as inSampleSize value, this will
            // guarantee a final image
            // with both dimensions larger than or equal to the requested height
            // and width.
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;

            // This offers some additional logic in case the image has a strange
            // aspect ratio. For example, a panorama may have a much larger
            // width than height. In these cases the total pixels might still
            // end up being too large to fit comfortably in memory, so we should
            // be more aggressive with sample down the image (=larger
            // inSampleSize).

            final float totalPixels = width * height;

            // Anything more than 2x the requested pixels we'll sample down
            // further
            final float totalReqPixelsCap = reqWidth * reqHeight * 2;

            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++;
            }
        }
        return inSampleSize;
    }

    public void openGallery(Context context) {
        Intent intent = new Intent(Intent.ACTION_VIEW,
                Uri.parse("content://media/internal/images/media"));
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }

    private void convertToBase64(Bitmap bitmap) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        bitmap.compress(CompressFormat.JPEG, 30, byteArrayOutputStream);
        byte[] byteArray = byteArrayOutputStream.toByteArray();
        String encoded = Base64.encodeToString(byteArray, Base64.NO_WRAP);

        // bitmap.recycle();

        encoded = null;
        byteArray = null;
    }

    public String getImageDirectory() {

        return createDirIfNotExists().getAbsolutePath();
    }

    public File createDirIfNotExists() {

        File imageDirectory = new File(
                Environment.getExternalStorageDirectory(), CAM_DIRECTORY);
        if (!imageDirectory.exists()) {

            if (!imageDirectory.mkdirs()) {

                Log.e("imageDirectory :: ", "Problem creating Image folder");
            }
        }
        return imageDirectory;
    }

}

本级采取图片&安培;在后台任务手柄转动

This class take pics & handle rotation in background task

package com.serveroverload.cube.ui;

import java.io.File;
import java.io.IOException;
import java.util.Calendar;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.camtest.R;
import com.serveroverload.cube.controller.CamerHandler;

public class HomeActivity extends Activity {

    static final int REQUEST_IMAGE_CAPTURE = 1;
    private ImageView previewLayout;
    private static final String TAG = "MainActivity";

    static Uri capturedImageUri = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);

        // Imageview to display Image
        previewLayout = (ImageView) findViewById(R.id.preview);

        findViewById(R.id.take_picture).setOnClickListener(
                new OnClickListener() {

                    @Override
                    public void onClick(View v) {
                        dispatchTakePictureIntent();

                    }
                });

    }

    private void dispatchTakePictureIntent() {

        Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");

        if (intent.resolveActivity(getPackageManager()) != null) {

            Calendar cal = Calendar.getInstance();

            // store image in new File in image directory
            File file = new File(CamerHandler.GetCamerHandlerInstance()
                    .getImageDirectory(), (cal.getTimeInMillis() + ".png"));

            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(),
                            "Failed to make file", 500).show();
                }
            } else {
                file.delete();
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(),
                            "Failed to make file", 500).show();
                }
            }

            capturedImageUri = Uri.fromFile(file);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, capturedImageUri);
            startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
        }

    }

    @SuppressLint("NewApi")
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK && requestCode == REQUEST_IMAGE_CAPTURE) {

            // update file in gallery
            sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,
                    capturedImageUri));

            // Downsample image before displaying in imageview to avoi OOM
            // exception
            new LoadBitMap(previewLayout, HomeActivity.this)
                    .execute(capturedImageUri);

        } else {
            Log.e(TAG, "FAILED TO TAKE IMAGE");
        }
    }

}

class LoadBitMap extends AsyncTask<Uri, Void, Void> {

    public LoadBitMap(ImageView preview, Context context) {
        this.prevImageView = preview;
        this.mContext = context;
    }

    private Bitmap bitmap = null;
    private ImageView prevImageView;
    private Context mContext;

    @Override
    protected Void doInBackground(Uri... params) {
        try {

            bitmap = CamerHandler.GetCamerHandlerInstance()
                    .handleSamplingAndRotationBitmap(mContext, params[0]);

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        if (null != bitmap) {

            prevImageView.setBackground(new BitmapDrawable(mContext
                    .getResources(), bitmap));
        }
        super.onPostExecute(result);
    }
}

测试布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true"
    android:orientation="vertical"
    android:background="#000"
    tools:context="com.serveroverload.cube.ui.HomeActivity" >

    <ImageView
        android:background="#fff"
        android:id="@+id/preview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/take_picture"
        android:layout_alignParentTop="true"
        android:layout_margin="5dp" />

    <ImageView

        android:id="@+id/take_picture"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:layout_margin="10dp"
        android:padding="5dp"
        android:scaleType="fitXY"
        android:src="@drawable/take_pic" />

</RelativeLayout>

结果是这样的

这篇关于setDisplayOrientation摄像头做了错误的方向时,保存图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆