需要 25 秒以上才能将位图从相机保存到 Phone

Takes 25+ Seconds To Save Bitmap From Camera To Phone

我正在制作相机应用程序。

由于某些手机不写入 EXIF 方向数据,因此在获得正确方向方面存在许多问题。因此,我得到位图,保存它(因为我认为我不应该从字节 [] 中读取 EXIF 数据),然后旋转位图,然后保存在原始文件上。

有效,方向问题已解决。问题是我在某些顶级手机上花费了 25 秒或更长时间。你能告诉我为什么我的代码这么慢,或者告诉我如何找到问题吗?

注意:如果我只保存一次图像(即方向错误),则只需要几秒钟。

这是我的图像捕获回调:

private Camera.PictureCallback pictureCallback = new Camera.PictureCallback()
{
    @Override
    public void onPictureTaken(byte[] data, Camera camera)
    {
        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null){
            Log.d("EditPhotoFragment", "Error creating media file, check storage permissions");
            return;
        }
        try
        {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            fos.write(data);
            fos.flush();
            fos.close();

            orientPicture(pictureFile);

            //TODO async
            galleryAddPic(pictureFile);
        } catch (FileNotFoundException e) {
            Log.d("EditPhotoFragment", "File not found: " + e.getMessage());
        } catch (IOException e) {
            Log.d("EditPhotoFragment", "Error accessing file: " + e.getMessage());
        }
    }
};

这是我定位并重新保存图像的位置:

private Bitmap orientPicture(File pictureFile)
    {
        Bitmap bitmap = BitmapFactory.decodeFile(pictureFile.getAbsolutePath());
        Uri uri = Uri.parse(pictureFile.toString());
        ExifInterface exif = null;
        try{
            exif = new ExifInterface(uri.getPath());

        }catch (Exception e)
        {
            e.printStackTrace();
        }
        int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
        Matrix matrix = new Matrix();
        int rotationInDegrees = 0;
        //If the orientation tag is missing need to manually rotate it by the 'default' camera
        //orientation and if its front facing need to do 360 - the camera rotation value
        if(exifOrientation == ExifInterface.ORIENTATION_UNDEFINED)//All phones in this bucket can go fuck themselves
        {
            Camera.CameraInfo info = new Camera.CameraInfo();
            if(_cameraPreview.isBackFacing())
            {
                Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
            }else
            {
                Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
            }
            rotationInDegrees = info.orientation; //set it to the default camera orientation
        }else
        {
            rotationInDegrees = exifToDegrees(exifOrientation);
            if(!_cameraPreview.isBackFacing())//handle mirroring of front camera
            {
                Camera.CameraInfo info = new Camera.CameraInfo();
                Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, info);
                rotationInDegrees = 360 - rotationInDegrees; //For the front camera doing 360 - gets the right orientation
            }
        }
        matrix.preRotate(rotationInDegrees);
        if(!_cameraPreview.isBackFacing())//mirror it
        {
            matrix.preScale(1,-1);
        }
        Bitmap adjustedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);

        //This saves the proper image over top if it
        try
        {
            FileOutputStream fos = new FileOutputStream(pictureFile);
            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            adjustedBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
            byte[] byteArray = stream.toByteArray();
            fos.write(byteArray);
            fos.flush();
            fos.close();
        }catch(Exception e)
        {
            e.printStackTrace();
        }


        return adjustedBitmap;
    }

解决方案 正如我所建议的那样,我应该阅读 exif 数据,由于这个原因,我不需要外部库就可以做到这一点:

Can you advise why my code is so slow

可能出于其他原因,您正在将图像写入文件,从文件中重新读取同一图像,进行转换,然后将图像写回文件。那会花很多时间。

Note: If I only save the image once (i.e. with the wrong orientation) it only takes a couple seconds.

那是因为你做的工作少了很多,只包括 ~33% 的磁盘 I/O,而且磁盘 I/O 会变慢。

since I don't think I should read EXIF data from the byte[]

如果您在小时候受到 byte[] 恶意攻击,我深表歉意。但是,如果您想要更好的性能,您将不得不从图像的现有内存副本中读取 EXIF 数据。