【问题标题】:Image gets rotated on Note 10 and One Plus devices in android studio图像在 android studio 的 Note 10 和 One Plus 设备上旋转
【发布时间】:2020-11-10 14:18:57
【问题描述】:

我需要上传一张图片到服务器。为此,我捕获图像(或从图库中获取图像)该图像被放置在其确切位置,但是当我将图像上传到服务器时,图像被旋转。 我也用谷歌搜索过,但没有运气。
以下是我的代码:

private fun chooseImage() {
        val items = arrayOf<CharSequence>("Camera", "Gallery", "Cancel")
        val builder = AlertDialog.Builder(this)
        builder.setTitle("Add Attachment")
        builder.setItems(items) { dialog, item ->
            try {
                if (items[item] == "Camera") {
                    takePhotoFromCamera()

                } else if (items[item] == "Gallery") {
                    choosePhotoFromGallary()

                } else if (items[item] == "Cancel") {
                    dialog.dismiss()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        builder.show()
    }

    fun choosePhotoFromGallary() {
        val galleryIntent = Intent(
            Intent.ACTION_PICK,
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI
        )
        startActivityForResult(galleryIntent, GALLERY)
    }

    private fun takePhotoFromCamera() {
        val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        startActivityForResult(intent, CAMERA)
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if (requestCode == GALLERY) {
            if (data != null) {
                val contentURI: Uri = data.getData()
                try {
                    var bitmap =
                        MediaStore.Images.Media.getBitmap(this.contentResolver, contentURI)
                    imagePath = bitmapToFile(bitmap,this).toString()

                   var bitmapNew =  handleSamplingAndRotationBitmap(this,contentURI)

                    binding.circleImageView.setImageBitmap(bitmapNew)
                    AppInstance.profileimagePath = imagePath

                } catch (e: IOException) {
                    e.printStackTrace()
                    showToast(this, "Failed!")
                }
            }
        } else if (requestCode == CAMERA) {
            val thumbnail = data!!.getExtras().get("data") as Bitmap

            imagePath= bitmapToFile(thumbnail,this).toString()

            Glide.with(this)
                .load(imagePath).into(binding.circleImageView);

            AppInstance.profileimagePath = imagePath


        }
    }

这是:

 @Throws(IOException::class)
    public fun handleSamplingAndRotationBitmap(context: Context, selectedImage: Uri?): Bitmap? {
        val MAX_HEIGHT = 800
        val MAX_WIDTH = 800

        // First decode with inJustDecodeBounds=true to check dimensions
        val options = BitmapFactory.Options()
        options.inJustDecodeBounds = true
        var imageStream: InputStream = 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)
        var img = BitmapFactory.decodeStream(imageStream, null, options)
        img = selectedImage?.let { rotateImageIfRequired(context, img, it) }
        return img
    }

位图到文件:

fun bitmapToFile(bitmap: Bitmap, context: Context): Uri {
    // Get the context wrapper
    val dateFormat = SimpleDateFormat("yyyyMMdd_HH_mm_ss")
    val currentTimeStamp = dateFormat.format(Date())
    val wrapper = ContextWrapper(context)

    // Initialize a new file instance to save bitmap object
    var file = wrapper.getDir("Images",Context.MODE_PRIVATE)
    file = File(file,"$currentTimeStamp.jpg")

    var bitmapNew = bitmap

    try{
        val imageRotation: Int = getImageRotation(file)
        if (imageRotation != 0)
            bitmapNew = getBitmapRotatedByDegree(bitmap, imageRotation)!!

        // Compress the bitmap and save in jpg format
        val stream: OutputStream = FileOutputStream(file)
        bitmapNew.compress(Bitmap.CompressFormat.JPEG,70,stream)
        stream.flush()
        stream.close()
    }catch (e: IOException){
        e.printStackTrace()
    }

    // Return the saved bitmap uri
    return Uri.parse(file.absolutePath)
}

我们将非常感谢您的支持。 提前致谢。

【问题讨论】:

  • val imageRotation: Int = getImageRotation(file) 您不应该从 File 对象而是从原始 data.getData() uri 中获取旋转。 10 岁以下不要使用 File 类。
  • 现在解决了吗?
  • @AnshulTyagi 是的,实际上问题出在 bitmaptoFile 函数上。我改变了它并且它有效:)

标签: android android-studio kotlin file-upload bitmapimage


【解决方案1】:

我认为您应该使用正确的 Exif 界面来确定正确的图像方向。

图像的方向与捕获它的传感器相关联。传感器方向是硬件组装和放入外壳(电话/设备)的方式。一些制造商/设备的相机物理旋转(出于“原因”),并被编程为写入指示正确旋转的 Exif 信息。

这是什么意思?

在实践中,这意味着在您拍摄/接收图像之后,您必须确保在对其进行操作之前阅读此 Exif 旋转。

以下是您需要的非常简单的(伪代码)。

(注:目前最新版本,2020 年 7 月,1.2.0

  1. 导入 Google EXIF 依赖:implementation "androidx.exifinterface:exifinterface:$exifinterfaceVersion"

  2. 假设您有一个指向图像的文件...您将拥有这样的函数:

 private fun getImageRotation(imageFile: File): Int {
        val ei = ExifInterface(imageFile.path)
        return ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_UNDEFINED)
    }
  1. 从Exif接口获取旋转后,你可以对其进行操作,假设你要旋转不“正常”的图像;你可以这样做:
fun ensureRotationIsNormal(imageBitmap: Bitmap, imageFile: File): Bitmap {
        try {
            val angle = when (getImageRotation(imageFile)) {
                ExifInterface.ORIENTATION_ROTATE_90 -> 90
                ExifInterface.ORIENTATION_ROTATE_180 -> 180
                ExifInterface.ORIENTATION_ROTATE_270 -> 270
                // these are already correctly oriented, return the image.
                ExifInterface.ORIENTATION_NORMAL -> return imageBitmap
                else -> return imageBitmap
            }

            return rotateBitmapWithAngle(imageBitmap, angle.toFloat())

        } catch (e: IOException) {
            Log.e(TAG, "Couldn't rotate image. Exception: " + e.message)
            return imageBitmap
        }
    }

rotate 的乐趣很简单:

    fun rotateBitmapWithAngle(imageBitmap: Bitmap, angle: Float): Bitmap {
        val matrix = Matrix()
        matrix.postRotate(angle)
        return Bitmap.createBitmap(
           imageBitmap, 
           0, 
           0, 
           imageBitmap.width, 
           imageBitmap.height, 
           matrix, 
           true)
    }

值得一提的是createBitmap的所有参数:

     * @param source   The bitmap we are subsetting
     * @param x        The x coordinate of the first pixel in source
     * @param y        The y coordinate of the first pixel in source
     * @param width    The number of pixels in each row
     * @param height   The number of rows
     * @param m        Optional matrix to be applied to the pixels
     * @param filter   true if the source should be filtered.
     *                   Only applies if the matrix contains more than just
     *                   translation.

我以前用过这个类似的方法。不确定是否有更好的方法,但这有效。您将需要决定您想要在“ensureRotationIsNormal”中使用什么“逻辑”,以及您想要的任何其他业务规则,但这些是“核心”部分。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 2012-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多