当前位置: 首页 > 知识库问答 >
问题:

为什么通过相机意图捕获图像后图像会旋转?

拓拔富
2023-03-14

我已经被困在相机里6天了,但没有得到任何适当的解决方案。当我通过相机意图捕获图像时,图像正在旋转。我试图修复方向,但有时它没有在onActivityResult()中给出位图值。当我尝试在ImageView中设置图像时,它会显示一个黑色屏幕。这是我的密码请帮帮我-

//call intent to capture image
captureBtn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                try {
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            if (takePictureIntent.resolveActivity(getActivity().getPackageManager()) != null) 
            {
                startActivityForResult(takePictureIntent,AlletConstants.CAPTURE_RECEIPT_IMAGE);
            }

        } catch (Exception e) {

            e.printStackTrace();
        }
            }
});


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

        switch (requestCode) {
        case AlletConstants.CAPTURE_RECEIPT_IMAGE:
            if(data != null)
            {
                Uri qrcodeImageUri = data.getData();
                bitmapReceiptImage = handleQrBarCodeImage(qrcodeImageUri);
                mImageCaptureUri = AlletCommonUtility.bitmapToUri(getActivity(), bitmapReceiptImage);
                doCrop();
                AlletCommonUtility.showToast(getActivity(),"Uri = "+mImageCaptureUri);
            }

            break;

        case AlletConstants.CROP_RECEIPT_FROM_CAMERA:
            if(data != null)
            {
                Bundle qrcodeextras = data.getExtras();
                if (qrcodeextras != null) {
                    Bitmap cropBitmap = qrcodeextras.getParcelable("data");
                    receiptImageView.setImageBitmap(cropBitmap);
                    bitmapReceiptImage = cropBitmap;
                }

                File qrcodeFile = new File(mImageCaptureUri.getPath());
                if (qrcodeFile.exists())
                    qrcodeFile.delete();
            }

            break;      

        default:
            break;
        }

    }




// use to get bitmap from uri 
    private Bitmap handleReceiptImage(Uri selectedImageUri)
    {       
        String[] filePathColumn = {MediaStore.Images.Media.DATA };  

        Cursor cursor = getActivity().getContentResolver().query(selectedImageUri, filePathColumn, null, null, null);  
        cursor.moveToFirst();  

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);  
        picturePath = cursor.getString(columnIndex);  
        cursor.close(); 
        Bitmap bitmap = setCameraImageRotation(picturePath);
        return bitmap;
    }

    private Bitmap setCameraImageRotation(String picturePath)
    {
        Bitmap bitmapQrBarImage = null;
         try {
                File f = new File(picturePath);
                ExifInterface exif = new ExifInterface(f.getPath());
                int orientation =  exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);      
                AlletCommonUtility.showToast(getActivity(), "Orienattion = "+orientation);
                Matrix mat = new Matrix();
                mat.postRotate(getImageOrientation(orientation));
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inSampleSize= 4;
                Bitmap bmp = BitmapFactory.decodeStream(new FileInputStream(f), null, options);
                bitmapQrBarImage = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), mat, true);     

                if (bitmapQrBarImage != null) {
                     AlletCommonUtility.showToast(getActivity(), "CAMERA_PIC_SELECTION = "+bitmapQrBarImage);
                }
            }
            catch (IOException e) {
                Log.w("TAG", "-- Error in setting image");
            }   
            catch(OutOfMemoryError oom) {
                Log.w("TAG", "-- OOM Error in setting image");
            }

         return bitmapQrBarImage;

    }



// Use to crop image
    private void doCrop() {
        final ArrayList<CropOption> cropOptions = new ArrayList<CropOption>();
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setType("image/*");

        List<ResolveInfo> list = getActivity().getPackageManager().queryIntentActivities( intent, 0 );

        int size = list.size();

        if (size == 0) {       
            AlletCommonUtility.showToast(getActivity(), AlletMessage.NOT_CROP_IMAGE);           
            return;
        } else {
            intent.setData(mImageCaptureUri);

            intent.putExtra("outputX", 200);
            intent.putExtra("outputY", 200);
            intent.putExtra("aspectX", 1);
            intent.putExtra("aspectY", 1);
            intent.putExtra("scale", true);
            intent.putExtra("return-data", true);

            if (size == 1) {
                Intent i        = new Intent(intent);
                ResolveInfo res = list.get(0);

                i.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
                startActivityForResult(i, AlletConstants.CROP_RECEIPT_FROM_CAMERA);

            } else {
                for (ResolveInfo res : list) {
                    final CropOption co = new CropOption();

                    co.title    = getActivity().getPackageManager().getApplicationLabel(res.activityInfo.applicationInfo);
                    co.icon     = getActivity().getPackageManager().getApplicationIcon(res.activityInfo.applicationInfo);
                    co.appIntent= new Intent(intent);

                    co.appIntent.setComponent( new ComponentName(res.activityInfo.packageName, res.activityInfo.name));

                    cropOptions.add(co);
                }

                CropOptionAdapter adapter = new CropOptionAdapter(getActivity(), cropOptions);

                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
                builder.setTitle("Choose Crop App");
                builder.setAdapter( adapter, new DialogInterface.OnClickListener() {
                    public void onClick( DialogInterface dialog, int item ) {
                        startActivityForResult( cropOptions.get(item).appIntent, AlletConstants.CROP_RECEIPT_FROM_CAMERA); 
                    }
                });

                builder.setOnCancelListener( new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel( DialogInterface dialog ) {

                        if (mImageCaptureUri != null ) {
                            getActivity().getContentResolver().delete(mImageCaptureUri, null, null );
                            mImageCaptureUri = null;
                        }
                    }
                } );

                AlertDialog alert = builder.create();

                alert.show();
            }
        }
    }



// use to rotate captured image from device camera 
public static int getImageOrientation(int rotation)
    {
         int angle = 0;

            switch (rotation) {
            case 0:
                angle = 90;
                break;

            case ExifInterface.ORIENTATION_ROTATE_90:
                angle = 90;
                break;

            case ExifInterface.ORIENTATION_ROTATE_180:
                angle = 180;
                break;

            case ExifInterface.ORIENTATION_ROTATE_270:
                angle = 270;
                break;
            default:
                break;
            }

            return angle;

    }

我得到的图像在横向模式,但不是在potrait模式。相机预览在拍摄图像后自动旋转90度。

共有2个答案

傅志诚
2023-03-14

根据您的内置摄像头方向和设备方向,图片将有不同的旋转。您可以通过ExifInterface检查特定图像的旋转。

/**
 * @param filename      Path to image file
 * @param captureTime   Time when image file was created
 */
public static int extractExifOrientationTagFromImageFile(String filename, long creationTime) {
    /* The issue is on some devices, there's a bug that makes the picture taken saved in your app folder without proper 
       exif tags while a properly rotated image is saved in the android default folder (even though it shouldn't be).
       Now what we do is recording the time when we're starting the camera app. Then we query
       the Media Provider to see if any pictures were saved after this timestamp we've saved. That means most likely Android OS 
       saved the properly rotated picture in the default folder and of course put an entry in the media store and we can use the 
       rotation information from this row.  */
    int imageRotation = -1;
    long imageFileSize = new File(filename).length();

    Cursor mediaFileCursor = getContext().getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
            new String[] { MediaStore.Images.ImageColumns.ORIENTATION, MediaStore.MediaColumns.SIZE }, 
            MediaStore.MediaColumns.DATE_ADDED + " >= ?", new String[] { String.valueOf(creationTime / 1000 - 1) }, 
            MediaStore.MediaColumns.DATE_ADDED + " DESC");
    if((mediaFileCursor != null) && (mediaFileCursor.getCount() != 0)) {
        while(mediaFileCursor.moveToNext()) {
            long mediaFileSize = getLongFromCursor(mediaFileCursor, MediaStore.MediaColumns.SIZE);
            // Extra check to make sure that we are getting the orientation from the proper file
            if(mediaFileSize == imageFileSize) {
                imageRotation = getIntFromCursor(mediaFileCursor, MediaStore.Images.ImageColumns.ORIENTATION);
                break;
            }
        }
    }

    /* Now if the rotation at this point is still -1, then that means this is one of the devices with proper rotation information. */
    if(imageRotation == -1) {
        ExifInterface exif = null;
        try {
            exif = new ExifInterface(filename);
        } 
        catch (IOException e) {
            e.printStackTrace();
        }
        imageRotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
    }

    return imageRotation;
}

private static final int COLUMN_NOT_EXISTS = -1;

public static Long getLongFromCursor(Cursor cursor, String columnName) {
    int columnIndex;
    if((columnIndex = cursor.getColumnIndex(columnName)) != COLUMN_NOT_EXISTS) {
        return cursor.getLong(columnIndex);
    }
    else {
        return null;
    }
}

public static Integer getIntFromCursor(Cursor cursor, String columnName) {
    int columnIndex;
    if((columnIndex = cursor.getColumnIndex(columnName)) != COLUMN_NOT_EXISTS) {
        return cursor.getInt(columnIndex);
    }
    else {
        return null;
    }
}

现在,当您进行图像旋转时,可以正确旋转其位图:

int imageRotation = extractExifOrientationTagFromImageFile(lastCapturedMediaUriPath, cameraAppInvokeTime);
Matrix matrix = new Matrix();
switch(imageRotation) {
    case ExifInterface.ORIENTATION_ROTATE_90:
        matrix.postRotate(90);
        break;
    case ExifInterface.ORIENTATION_ROTATE_180:
        matrix.postRotate(180);
        break;
    case ExifInterface.ORIENTATION_ROTATE_270:
        matrix.postRotate(270);
        break;
    default:
        break;
}
final Bitmap loadedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
咸亦
2023-03-14

这是因为图像的EXIF数据。您需要使用旋转方法。

 类似资料:
  • 当我捕获照片时,在某些设备中,它会以景观模式存储在某些设备中,它会存储肖像。我想让图像在肖像模式无论如何。为此,我尝试获取图像的数据,并相应地将其旋转到肖像模式。但在一些设备,如三星,VIVO的方向值得到“0”。我不知道该怎么处理那个值。如果我90,那么一些设备将解决此问题,而另一些设备将向上保存照片。 我从Xamarin那里得到这个主意。Andoid图像旋转。但不知怎的,我不能再继续下去了。会有

  • 我已经开发了一个应用程序来拍摄一张照片并保存在画廊里。我在网上搜索过,我能练习的最简单的方法就是使用。下面是从相机上拍照的代码。注意,我在这个类中使用的是fragment。 获取捕获的图像并将其转换为字符串 我将字符串保存到全局变量中,以便其他活动可以访问它。在另一个活动中,我有一个按钮,通过访问图像字符串将图像保存到文件夹/图库中。 它可以将图像保存到文件夹/图库中......但是图像质量很低.

  • 我正在捕获一个图像并将其设置为图像视图。 但问题是,一些设备上的图像每次被旋转。例如,在三星的设备上,它运行良好,但在索尼的Xperia上,图像会旋转90度,在东芝的Thrive(平板电脑)上旋转180度。

  • 我发现了一个非常有趣的问题。在拍摄相机照片后(我将设备保持在纵向模式,不旋转),给定的照片有时会旋转,但并不总是旋转。我知道,有些设备总是提供旋转的照片,但它可以使用exif或mediastore信息进行旋转。但在这种情况下,exif和mediastore表示方向为0,但图像是旋转的。最令人沮丧的是,这完全是随机发生的。代码非常简单: 有人见过这个问题吗?我在操作系统更新(4.1.1)后体验了Ga

  • 我有以下代码,它要求用户从照片应用程序中选择一个图像或通过相机应用程序捕捉一个图像: 和OnActivityResult的代码:

  • 在我的应用程序中,用户从相机捕获图像或从图库中选择图像,然后将其转换为pdf并上载到服务器,现在我的问题是,从相机捕获的图像在某些设备上旋转,我有代码尝试解决此问题,但它不起作用 任何建议或问题在哪里,没有错误代码或任何东西