草庐IT

android - 图像压缩,如 Whatsapp 和 Android 上的其他信使

coder 2023-06-09 原文

我正在使用以下代码进行图像压缩。

代码压缩大于 2 MB 的图像文件。

但此代码需要时间,而且图像质量保持纯净。

public static String compressImage(String imagePath, Context context)
    {
        String resizeImagePath = null;
        String filePath = imagePath;
        CustomLogHandler.printDebug(TAG, "resizeImagePath:" + imagePath);
        Bitmap scaledBitmap = null;
        int imageScal = 1;

        // File size greater then 2mb
        DecimalFormat df = new DecimalFormat("0.00");
        File imgFile = new File(filePath);
        double bytes = imgFile.length();
        double kilobytes = (bytes / 1024);
        double megabytes = (kilobytes / 1024);

        AppConfig.makeLog(TAG, "image size in mb:" + df.format(megabytes), 0);

        double filesize = Double.parseDouble(df.format(megabytes));
        if (filesize > 2.00f)
        {

            for (int i = 0; i < filesize; i = i + 2)
            {

                imageScal++;
            }
            int remind = imageScal / 2;
            if (remind != 0)
            {
                imageScal = imageScal + 1;
            }

            makeLog(TAG, "image scale:" + imageScal, 0);

            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            Bitmap bmp = BitmapFactory.decodeFile(filePath, options);

            int actualHeight = options.outHeight;
            int actualWidth = options.outWidth;
            float maxHeight = 4000;
            float maxWidth = 6000;
            // float imgRatio = actualWidth / actualHeight;
            // float maxRatio = maxWidth / maxHeight;

            if (actualHeight > maxHeight)
            {
                imageScal = imageScal + 4;
            }

            if (actualWidth > maxWidth)
            {
                imageScal = imageScal + 8;
            }

            // if (actualHeight > maxHeight || actualWidth > maxWidth)
            // {
            // if (imgRatio < maxRatio)
            // {
            // imgRatio = maxHeight / actualHeight;
            // actualWidth = (int) (imgRatio * actualWidth);
            // actualHeight = (int) maxHeight;
            //
            // }
            // else if (imgRatio > maxRatio)
            // {
            // imgRatio = maxWidth / actualWidth;
            // actualHeight = (int) (imgRatio * actualHeight);
            // actualWidth = (int) maxWidth;
            // }
            // else
            // {
            // actualHeight = (int) maxHeight;
            // actualWidth = (int) maxWidth;
            //
            // }
            // }

            // options.inSampleSize = utils.calculateInSampleSize(options, actualWidth, actualHeight);
            options.inSampleSize = imageScal;
            options.inJustDecodeBounds = false;
            options.inDither = true;
            options.inPurgeable = true;
            options.inInputShareable = true;
            options.inTempStorage = new byte[16 * 1024];

            try
            {
                bmp = BitmapFactory.decodeFile(filePath, options);
                bmp = decodeFile(filePath);
            }
            catch (OutOfMemoryError exception)
            {
                exception.printStackTrace();

            }
            boolean done = false;

            while (!done)
            {
                try
                {
                    scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);

                    // scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.ARGB_8888);

                    done = true;
                }
                catch (OutOfMemoryError exception)
                {
                    // 15923 × 1790
                    // 5616 × 3744
                    // 8150 × 9154
                    actualWidth = actualWidth - ((actualWidth * 2) / 100);
                    actualHeight = actualHeight - ((actualHeight * 2) / 100);
                    // scaledBitmap = Bitmap.createBitmap(5616, 3744, Bitmap.Config.ARGB_8888);
                    exception.printStackTrace();
                }

            }

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

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

            Canvas canvas = new Canvas(scaledBitmap);
            canvas.setMatrix(scaleMatrix);
            canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));

            // Resize image stored in sdcard
            FileOutputStream out = null;
            // filename =AppConfig.fileTosaveMedia(context, FileType.IMAGE, true).getAbsolutePath();
            int compress = 50;
            try
            {
                do
                {
                    imgFile = AppConfig.fileTosaveMedia(context, FileType.IMAGE, true);
                    out = new FileOutputStream(imgFile);
                    scaledBitmap.compress(Bitmap.CompressFormat.JPEG, compress, out);

                    resizeImagePath = imgFile.getAbsolutePath();

                    // Thread.sleep(15000);
                    // imgFile = new File(filename);
                    bytes = imgFile.length();
                    kilobytes = (bytes / 1024);
                    megabytes = (kilobytes / 1024);
                    System.out.println("resized image size in mb:" + df.format(megabytes));

                    filesize = Double.parseDouble(df.format(megabytes));
                    if (filesize > 2.00f)
                    {
                        compress = 30;
                    }
                } while (filesize > 2.00f);
                scaledBitmap.recycle();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        else
        {

            FileOutputStream out = null;
            // FileInputStream in = null;
            imgFile = AppConfig.fileTosaveMedia(context, FileType.IMAGE, true);
            resizeImagePath = imgFile.getAbsolutePath();
            InputStream in = null;
            OutputStream outTemp = null;
            try
            {

                // create output directory if it doesn't exist

                in = new FileInputStream(filePath);
                outTemp = new FileOutputStream(resizeImagePath);

                byte[] buffer = new byte[1024];
                int read;
                while ((read = in.read(buffer)) != -1)
                {
                    outTemp.write(buffer, 0, read);
                }
                in.close();
                in = null;

                // write the output file (You have now copied the file)
                outTemp.flush();
                outTemp.close();
                outTemp = null;

            }
            catch (FileNotFoundException fnfe1)
            {
                Log.e("tag", fnfe1.getMessage());
            }
            catch (Exception e)
            {
                Log.e("tag", e.getMessage());
            }

            // try
            // {
            // Bitmap bmp = decodeFile(filePath);
            // // in = new FileInputStream(new File(imagePath));
            // // persistImage(bitmap, name);
            // out = new FileOutputStream(resizeImagePath);
            // bmp.compress(Bitmap.CompressFormat.JPEG, 100, out);
            // out.flush();
            // out.close();
            // // FileIO.copyStream(in, out);
            // }
            // catch (Exception e)
            // {
            // e.printStackTrace();
            // }
        }
        CustomLogHandler.printDebug(TAG, "resizeImagePath:" + resizeImagePath);
        return resizeImagePath;
    }

我花了很多时间在 Google 搜索和阅读博客上。然后在创建上面的代码后,我发现this .

上面的代码正确吗?或者有没有其他库可以用来压缩图片?

请帮帮我。

最佳答案

试试下面的代码:-

public String compressImage(String imageUri) {

        String filePath = getRealPathFromURI(imageUri);
        Bitmap scaledBitmap = null;

        BitmapFactory.Options options = new BitmapFactory.Options();

//      by setting this field as true, the actual bitmap pixels are not loaded in the memory. Just the bounds are loaded. If
//      you try the use the bitmap here, you will get null.
        options.inJustDecodeBounds = true;
        Bitmap bmp = BitmapFactory.decodeFile(filePath, options);

        int actualHeight = options.outHeight;
        int actualWidth = options.outWidth;

//      max Height and width values of the compressed image is taken as 816x612

        float maxHeight = 816.0f;
        float maxWidth = 612.0f;
        float imgRatio = actualWidth / actualHeight;
        float maxRatio = maxWidth / maxHeight;

//      width and height values are set maintaining the aspect ratio of the image

        if (actualHeight > maxHeight || actualWidth > maxWidth) {
            if (imgRatio < maxRatio) {               imgRatio = maxHeight / actualHeight;                actualWidth = (int) (imgRatio * actualWidth);               actualHeight = (int) maxHeight;             } else if (imgRatio > maxRatio) {
                imgRatio = maxWidth / actualWidth;
                actualHeight = (int) (imgRatio * actualHeight);
                actualWidth = (int) maxWidth;
            } else {
                actualHeight = (int) maxHeight;
                actualWidth = (int) maxWidth;

            }
        }

//      setting inSampleSize value allows to load a scaled down version of the original image

        options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);

//      inJustDecodeBounds set to false to load the actual bitmap
        options.inJustDecodeBounds = false;

//      this options allow android to claim the bitmap memory if it runs low on memory
        options.inPurgeable = true;
        options.inInputShareable = true;
        options.inTempStorage = new byte[16 * 1024];

        try {
//          load the bitmap from its path
            bmp = BitmapFactory.decodeFile(filePath, options);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();

        }
        try {
            scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight,Bitmap.Config.ARGB_8888);
        } catch (OutOfMemoryError exception) {
            exception.printStackTrace();
        }

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

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

        Canvas canvas = new Canvas(scaledBitmap);
        canvas.setMatrix(scaleMatrix);
        canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));

//      check the rotation of the image and display it properly
        ExifInterface exif;
        try {
            exif = new ExifInterface(filePath);

            int orientation = exif.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION, 0);
            Log.d("EXIF", "Exif: " + orientation);
            Matrix matrix = new Matrix();
            if (orientation == 6) {
                matrix.postRotate(90);
                Log.d("EXIF", "Exif: " + orientation);
            } else if (orientation == 3) {
                matrix.postRotate(180);
                Log.d("EXIF", "Exif: " + orientation);
            } else if (orientation == 8) {
                matrix.postRotate(270);
                Log.d("EXIF", "Exif: " + orientation);
            }
            scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0,
                    scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix,
                    true);
        } catch (IOException e) {
            e.printStackTrace();
        }

        FileOutputStream out = null;
        String filename = getFilename();
        try {
            out = new FileOutputStream(filename);

//          write the compressed bitmap at the destination specified by filename.
            scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return filename;

    }

有关信息,请参阅以下链接:-

http://voidcanvas.com/whatsapp-like-image-compression-in-android/

关于android - 图像压缩,如 Whatsapp 和 Android 上的其他信使,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26928597/

有关android - 图像压缩,如 Whatsapp 和 Android 上的其他信使的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  4. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  5. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  6. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  7. ruby - 调用其他方法的 TDD 方法的正确方法 - 2

    我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent

  8. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. ruby-on-rails - 在 Ruby (on Rails) 中使用 imgur API 获取图像 - 2

    我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path

随机推荐