以矩形裁剪位图图像
Posted
技术标签:
【中文标题】以矩形裁剪位图图像【英文标题】:Crop bitmap image in rectangular 【发布时间】:2019-07-15 09:09:48 【问题描述】:我想在不使用任何库的情况下裁剪图像。
我正在参考https://***.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()
);
我想要一个矩形内的裁剪位图图像。
【问题讨论】:
【参考方案1】:为了有效地创建位图,试试这个
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)
传递你想要的高度和宽度
【讨论】:
感谢您的回复,我尝试了您的解决方案,但没有成功,图片没有被裁剪。 你遇到了什么问题 实际上我的 xml 框架宽度 = 260 和高度 =400 和图像边宽度 = 1080 高度 = 1920 您提供的解决方案按原样返回位图Scaled()
图片类返回给您的位是否与具有原始大小的实际图像一致?以上是关于以矩形裁剪位图图像的主要内容,如果未能解决你的问题,请参考以下文章