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

在上传到firebase android之前压缩多个图像

伍捷
2023-03-14

我正在开发应用程序,用户必须上传多个图像。现在我面临的问题是他们的规模。由于用户可以上传多个图像,这需要大量的时间来通过应用程序上传它们,因为它们太大了,用户不喜欢,也使我的应用程序和数据库沉重。你能指导我如何在上传多张图片到firebase之前压缩它们吗?

用于压缩图像的代码

  galleryResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
        @Override
        public void onActivityResult(ActivityResult result) {


                if (result.getResultCode() == RESULT_OK && null != result.getData() ) {

                    if (result.getData().getClipData() != null) {

                        int countofImages = result.getData().getClipData().getItemCount();
                        //this part is to select multiple images
                        for (int i = 0; i < countofImages; i++) {

                            if (uri.size() < 11) {
                                Uri imageuri = result.getData().getClipData().getItemAt(i).getUri();


                              
                                imageList.add(new CustomModel(getfilename(imageuri), imageuri));
                            } else {
                                Toast.makeText(getContext(), "Can't select more than 11 images", Toast.LENGTH_SHORT).show();
                            }
                        }
                        //then notify the adapter
                        adapter.notifyDataSetChanged();
                        rentSell3Binding.totalphotos.setText("Photos (" + imageList.size() + ")");
                    }
                        //this part is to select single image
                        else
                            {

                            if (uri.size()<11) {
                                Uri imageuri = result.getData().getData();

                                //and add the code to arryalist
                         
                                imageList.add(new CustomModel(getfilename(imageuri), imageuri));

                            }else
                            {

                                Toast.makeText(getContext(), "Can't select more than 11 images", Toast.LENGTH_SHORT).show();

                            }

                        //notify the adapter
                        adapter.notifyDataSetChanged();
                        rentSell3Binding.totalphotos.setText("Photos (" + imageList.size() + ")");
                    }
                }else
                {
                    Toast.makeText(getContext(), "You haven't selected any images", Toast.LENGTH_SHORT).show();

                }
            }


    });

模特班

public class CustomModel {

String imageName;
Uri imageURI;


public CustomModel(String imageName, Uri imageURI) {
    this.imageName = imageName;
    this.imageURI = imageURI;
}

public String getImageName() {
    return imageName;
}

public void setImageName(String imageName) {
    this.imageName = imageName;
}

public Uri getImageURI() {
    return imageURI;
}

public void setImageURI(Uri imageURI) {
    this.imageURI = imageURI;
}

}

引发异常

null pointer exception on the line File file = new File(SiliCompressor.with(getContext()).compress(FileUtils.getPath(getContext(), imageuri), new File(getContext().getCacheDir(), "temp")));

共有1个答案

隗昀
2023-03-14

是的,您可以通过以下函数压缩图像文件

@Throws(IOException::class)
fun File.compressImage(
    reqWidth: Float,
    reqHeight: Float,
    compressFormat: Bitmap.CompressFormat,
    quality: Int,
    destinationPath: String
): File {
    var fileOutputStream: FileOutputStream? = null
    val file = File(destinationPath).parentFile ?: return File(destinationPath)

    if (!file.exists()) {
        file.mkdirs()
    }
    try {
        fileOutputStream = FileOutputStream(destinationPath)
        // write the compressed bitmap at the destination specified by destinationPath.
        decodeSampledBitmapFromFile(this, reqWidth, reqHeight)?.compress(
            compressFormat,
            quality,
            fileOutputStream
        )
    } finally {
        if (fileOutputStream != null) {
            fileOutputStream.flush()
            fileOutputStream.close()
        }
    }

    return File(destinationPath)
}

@Throws(IOException::class)
private fun decodeSampledBitmapFromFile(
    imageFile: File,
    reqWidth: Float,
    reqHeight: Float
): Bitmap? {
    // First decode with inJustDecodeBounds=true to check dimensions

    val options = BitmapFactory.Options()
    options.inJustDecodeBounds = true
    var bmp: Bitmap? = BitmapFactory.decodeFile(imageFile.absolutePath, options)

    var actualHeight = options.outHeight
    var actualWidth = options.outWidth

    var imgRatio = actualWidth.toFloat() / actualHeight.toFloat()
    val maxRatio = reqWidth / reqHeight

    if (actualHeight > reqHeight || actualWidth > reqWidth) {
        // If Height is greater
        when {
            imgRatio < maxRatio -> {
                imgRatio = reqHeight / actualHeight
                actualWidth = (imgRatio * actualWidth).toInt()
                actualHeight = reqHeight.toInt()
            } // If Width is greater
            imgRatio > maxRatio -> {
                imgRatio = reqWidth / actualWidth
                actualHeight = (imgRatio * actualHeight).toInt()
                actualWidth = reqWidth.toInt()
            }
            else -> {
                actualHeight = reqHeight.toInt()
                actualWidth = reqWidth.toInt()
            }
        }
    }

    // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight)
    options.inJustDecodeBounds = false

    if (bmp != null && canUseForInBitmap(bmp, options)) {
        // inBitmap only works with mutable bitmaps, so force the decoder to
        // return mutable bitmaps.
        options.inMutable = true
        options.inBitmap = bmp
    }
    options.inTempStorage = ByteArray(16 * 1024)

    try {
        bmp = BitmapFactory.decodeFile(imageFile.absolutePath, options)
    } catch (exception: OutOfMemoryError) {
        exception.printStackTrace()
    }

    var scaledBitmap: Bitmap? = null
    try {
        scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888)
    } catch (exception: OutOfMemoryError) {
        exception.printStackTrace()
    }

    val ratioX = actualWidth / options.outWidth.toFloat()
    val ratioY = actualHeight / options.outHeight.toFloat()
    val middleX = actualWidth / 2.0f
    val middleY = actualHeight / 2.0f

    val scaleMatrix = Matrix()
    scaleMatrix.setScale(ratioX, ratioY, middleX, middleY)

    val canvas = Canvas(scaledBitmap!!)
    canvas.setMatrix(scaleMatrix)
    canvas.drawBitmap(
        bmp!!, middleX - bmp.width / 2,
        middleY - bmp.height / 2, Paint(Paint.FILTER_BITMAP_FLAG)
    )
    bmp.recycle()
    val exif: ExifInterface
    try {
        exif = ExifInterface(imageFile.absolutePath)
        val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0)
        val matrix = Matrix()
        if (orientation == 6) {
            matrix.postRotate(90f)
        } else if (orientation == 3) {
            matrix.postRotate(180f)
        } else if (orientation == 8) {
            matrix.postRotate(270f)
        }
        scaledBitmap = Bitmap.createBitmap(
            scaledBitmap, 0, 0, scaledBitmap.width,
            scaledBitmap.height, matrix, true
        )
    } catch (e: IOException) {
        e.printStackTrace()
    }

    return scaledBitmap
}

private fun calculateInSampleSize(
    options: BitmapFactory.Options,
    reqWidth: Int,
    reqHeight: Int
): Int {
    // Raw height and width of image
    val height = options.outHeight
    val width = options.outWidth
    var inSampleSize = 1

    if (height > reqHeight || width > reqWidth) {
        inSampleSize *= 2
        val halfHeight = height / 2
        val halfWidth = width / 2

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
            inSampleSize *= 2
        }
    }

    return inSampleSize
}

/**
 * Ref: https://developer.android.com/topic/performance/graphics/manage-memory#kotlin
 */
private fun canUseForInBitmap(candidate: Bitmap, targetOptions: BitmapFactory.Options): Boolean {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // From Android 4.4 (KitKat) onward we can re-use if the byte size of
        // the new bitmap is smaller than the reusable bitmap candidate
        // allocation byte count.
        val width: Int = targetOptions.outWidth / targetOptions.inSampleSize
        val height: Int = targetOptions.outHeight / targetOptions.inSampleSize
        val byteCount: Int = width * height * getBytesPerPixel(candidate.config)
        byteCount <= candidate.allocationByteCount
    } else {
        // On earlier versions, the dimensions must match exactly and the inSampleSize must be 1
        candidate.width == targetOptions.outWidth &&
                candidate.height == targetOptions.outHeight &&
                targetOptions.inSampleSize == 1
    }
}

/**
 * A helper function to return the byte usage per pixel of a bitmap based on its configuration.
 */
private fun getBytesPerPixel(config: Bitmap.Config): Int {
    return when (config) {
        Bitmap.Config.ARGB_8888 -> 4
        Bitmap.Config.RGB_565, Bitmap.Config.ARGB_4444 -> 2
        Bitmap.Config.ALPHA_8 -> 1
        else -> 1
    }
}

@Throws(IOException::class)
fun Context.createImageFile(): File {
    // Create an image file name
    val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    return File.createTempFile(
        "JPEG_${System.currentTimeMillis()}_", /* prefix */
        ".jpg", /* suffix */
        storageDir /* directory */
    )
}

并简单地调用以下方法来创建压缩图像文件。这里的文件是你的图像文件

file.compressImage(
                    1024f,
                    1024f,
                    Bitmap.CompressFormat.JPEG,
                    70,
                    context.createImageFile().path
                )
 类似资料:
  • 本文向大家介绍Android图片压缩上传之基础篇,包括了Android图片压缩上传之基础篇的使用技巧和注意事项,需要的朋友参考一下 在android程序开发中我们经常见到需要上传图片的场景,在这里有个技术点,需要把图片压缩处理,然后再进行上传。这样可以减少流量的消耗,提高图片的上传速度等问题。 关于android如何压缩,网上的资料也是很多,但大多数都是代码片段,讲解压缩步骤,而没有一个实用的工具

  • 我想在上传到Firebase存储之前减小图像文件大小,因为上传需要很长时间。 这是conatins编辑文本图像视图的表单 单击“保存”按钮时,我同时保存数据(在实时数据库中)和图像(存储)。 那么如何减少图像大小或压缩它呢??

  • 问题内容: 直接在手机上拍照后,我试图将图像文件上传到Parse。但这会引发异常: 由于未捕获的异常“ NSInvalidArgumentException”而终止应用程序,原因:“ PFFile不能大于10485760字节” 这是我的代码: 在第一视图控制器中: 在上传图像的视图控制器中: 但是我仍然需要将照片上传到Parse。有什么方法可以减小图像的尺寸或分辨率? 问题答案: 是的,你可以使用

  • 在上传到服务器之前,我使用了下面的方法来压缩图像。 为了总结下面的代码,我首先从phone/sdcard上获取图像,将其转换为位图,并对位图进行缩放和压缩。然后我将压缩后的位图保存在磁盘上,作为新位置的图像。 这种方法可以将图像从3mb-5mb压缩到30-100kb。(当我检查SD卡上的压缩图像大小时) 然后,我将新压缩的30-100kb图像转换为位图字符串(通过Base64.encodeToSt

  • Android API提供了保存位图对象的方法。我创建了一个示例应用程序,它将jpeg图像(一些嘈杂的相机照片)加载到位图中,然后将其压缩回同一个文件。然后,再做5次。 显然,我的位图积累了压缩伪影。让我惊讶的是,这些伪影的数量以一种奇怪的方式取决于压缩的质量。当我将质量设置为100(我认为这是最好的质量)时,工件清晰可见。当我将质量降低到90时,工件的可视性明显降低。质量设置为80会给我最好的效

  • 本文向大家介绍iOS实现压缩图片上传功能,包括了iOS实现压缩图片上传功能的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了iOS实现压缩图片上传功能,供大家参考,具体内容如下 以上就是本文的全部内容,希望对大家学习iOS程序设计有所帮助。