以矩形裁剪位图图像

时间:2019-07-15 09:09:48

标签: android bitmap crop

我想在不使用任何库的情况下裁剪图像。

我正在参考https://stackoverflow.com/a/6909144的内容,并尝试更改该值,但找不到解决方法

Bitmap bitmap = BitmapUtil.getBitmap(path);

                    Log.d(TAG,"bitmap  width : "+bitmap.getWidth()+"  height:  "+bitmap.getHeight());

                    if (bitmap.getWidth() >= bitmap.getHeight()){
                        Toast.makeText(this,"Height Greater",Toast.LENGTH_SHORT).show();
                        Log.d(TAG,"Greater : Height");
                        textView.setText("Height Greater");
                        bitmap = Bitmap.createBitmap(
                                bitmap,
                                bitmap.getWidth()/2 - bitmap.getHeight()/2,
                                0,
                                bitmap.getHeight(),
                                bitmap.getHeight()
                        );

                    }else{
                        Toast.makeText(this,"Width Greater",Toast.LENGTH_SHORT).show();
                        Log.d(TAG,"Greater : Width");
                        textView.setText("Width Greater");
                        bitmap = Bitmap.createBitmap(
                                bitmap,
                                0,
                                bitmap.getHeight()/2 - bitmap.getWidth()/2,
                                bitmap.getWidth(),
                                bitmap.getWidth()
                        );
                    }

我想要矩形内的裁剪位图图像。

enter image description here

1 个答案:

答案 0 :(得分:0)

要有效地创建位图,请尝试

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import java.io.ByteArrayOutputStream

    /**
     * 
     * ImageScalingUtils responsible for compressing the bitmap efficiently
     */
    object ImageScalingUtils {

        /**
         * Utility function for decoding an image resource. The decoded bitmap will
         * be optimized for further scaling to the requested destination dimensions
         * and scaling logic.
         *
         * @param dstWidth Width of destination area
         * @param dstHeight Height of destination area
         * @param scalingLogic Logic to use to avoid image stretching
         * @return Decoded bitmap
         */


        fun decodeBitmap(bm: Bitmap, dstWidth: Int, dstHeight: Int,
                         scalingLogic: ScalingLogic): Bitmap {
            val stream = ByteArrayOutputStream()
            bm.compress(Bitmap.CompressFormat.PNG, 100, stream)
            val byteArray = stream.toByteArray()
            val options = BitmapFactory.Options()
            options.inJustDecodeBounds = true
            BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)
            options.inJustDecodeBounds = false
            options.inSampleSize = calculateSampleSize(options.outWidth, options.outHeight, dstWidth,
                    dstHeight, scalingLogic)
            return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)
        }

        /**
         * ScalingLogic defines how scaling should be carried out if source and
         * destination image has different aspect ratio.
         *
         * CROP: Scales the image the minimum amount while making sure that at least
         * one of the two dimensions fit inside the requested destination area.
         * Parts of the source image will be cropped to realize this.
         *
         * FIT: Scales the image the minimum amount while making sure both
         * dimensions fit inside the requested destination area. The resulting
         * destination dimensions might be adjusted to a smaller size than
         * requested.
         */
        enum class ScalingLogic {
            CROP, FIT
        }

        /**
         * Calculate optimal down-sampling factor given the dimensions of a source
         * image, the dimensions of a destination area and a scaling logic.
         *
         * @param srcWidth Width of source image
         * @param srcHeight Height of source image
         * @param dstWidth Width of destination area
         * @param dstHeight Height of destination area
         * @param scalingLogic Logic to use to avoid image stretching
         * @return Optimal down scaling sample size for decoding
         */
        private fun calculateSampleSize(srcWidth: Int, srcHeight: Int, dstWidth: Int, dstHeight: Int,
                                        scalingLogic: ScalingLogic): Int {
            if (scalingLogic == ScalingLogic.FIT) {
                val srcAspect = srcWidth.toFloat() / srcHeight.toFloat()
                val dstAspect = dstWidth.toFloat() / dstHeight.toFloat()

                return if (srcAspect > dstAspect) {
                    srcWidth / dstWidth
                } else {
                    srcHeight / dstHeight
                }
            } else {
                val srcAspect = srcWidth.toFloat() / srcHeight.toFloat()
                val dstAspect = dstWidth.toFloat() / dstHeight.toFloat()

                return if (srcAspect > dstAspect) {
                    srcHeight / dstHeight
                } else {
                    srcWidth / dstWidth
                }
            }
        }


    }

可缩放图片类来缩放图片

 import android.content.ContentResolver
    import android.graphics.Bitmap
    import android.graphics.BitmapFactory
    import android.graphics.Matrix
    import android.graphics.RectF
    import android.net.Uri
    import androidx.exifinterface.media.ExifInterface
    import java.io.FileNotFoundException
    import java.io.IOException
    import java.io.InvalidObjectException

    /**
     *
     * ScaledPicture responsible for compressing the bitmap efficiently
     */
    class ScaledPicture(private var uri: Uri?, private var resolver: ContentResolver) {
        private var path: String? = null
        private var orientation: Matrix? = null
        private var storedHeight: Int = 0
        private var storedWidth: Int = 0

        @Throws(IOException::class)
        private fun getInformation(): Boolean {
            /*if (getInformationFromMediaDatabase())
                return true;*/
            return getInformationFromFileSystem()
        }

        /* Support for file managers and dropbox */
        @Throws(IOException::class)
        private fun getInformationFromFileSystem(): Boolean {
            path = uri?.path
            if (path == null)
                return false
            val exif = ExifInterface(path.toString())
            val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL)
            this.orientation = Matrix()
            when (orientation) {
                ExifInterface.ORIENTATION_NORMAL -> {
                }
                ExifInterface.ORIENTATION_FLIP_HORIZONTAL -> this.orientation?.setScale(-1f, 1f)
                ExifInterface.ORIENTATION_ROTATE_180 -> this.orientation?.setRotate(180f)
                ExifInterface.ORIENTATION_FLIP_VERTICAL -> this.orientation?.setScale(1f, -1f)
                ExifInterface.ORIENTATION_TRANSPOSE -> {
                    this.orientation?.setRotate(90f)
                    this.orientation?.postScale(-1f, 1f)
                }
                ExifInterface.ORIENTATION_ROTATE_90 -> this.orientation?.setRotate(90f)
                ExifInterface.ORIENTATION_TRANSVERSE -> {
                    this.orientation?.setRotate(-90f)
                    this.orientation?.postScale(-1f, 1f)
                }
                ExifInterface.ORIENTATION_ROTATE_270 -> this.orientation?.setRotate(-90f)
            }/* Identity matrix */
            return true
        }

        @Throws(IOException::class)
        private fun getStoredDimensions(): Boolean {
            val input = resolver.openInputStream(uri)
            val options = BitmapFactory.Options()
            options.inJustDecodeBounds = true
            BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options)
            /* The input stream could be reset instead of closed and reopened if it were possible
               to reliably wrap the input stream on a buffered stream, but it's not possible because
               decodeStream() places an upper read limit of 1024 bytes for a reset to be made (it calls
               mark(1024) on the stream). */

            input?.close()
            if (options.outHeight <= 0 || options.outWidth <= 0)
                return false
            storedHeight = options.outHeight
            storedWidth = options.outWidth
            return true
        }

        @Throws(IOException::class)
        fun getBitmap(reqWidth: Int, reqHeight: Int): Bitmap {
            val heightWidth = 1000
            if (!getInformation())
                throw FileNotFoundException()
            if (!getStoredDimensions())
                throw InvalidObjectException(null)
            val rect = RectF(0f, 0f, storedWidth.toFloat(), storedHeight.toFloat())
            orientation?.mapRect(rect)
            var width = rect.width().toInt()
            var height = rect.height().toInt()
            var subSample = 1
            while (width > heightWidth || height > heightWidth) {
                width /= 2
                height /= 2
                subSample *= 2
            }
            if (width == 0 || height == 0)
                throw InvalidObjectException(null)
            val options = BitmapFactory.Options()
            options.inSampleSize = subSample
            val subSampled = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options)
            val picture: Bitmap
            if (orientation?.isIdentity == false) {
                picture = Bitmap.createBitmap(subSampled, 0, 0, options.outWidth, options.outHeight,
                        orientation, false)
                subSampled.recycle()
            } else

                picture = subSampled

            return ImageScalingUtils.decodeBitmap(picture, reqWidth, reqHeight, ImageScalingUtils.ScalingLogic.CROP)
        }

    }

将上述类复制到您的项目中,并像这样使用它

var bitmap = ScaledPicture(mSelectedUri, contentResolver).getBitmap(800, 800)

传递所需的高度和宽度