草庐IT

Android位图压缩不好

coder 2023-12-16 原文

我得到了以下输出流代码:

        String output_file = APP_FILE_PATH + "/AudienceSignatures/" + CaptureSignature.this.sessionNumber + ".png";

        final FileOutputStream out = new FileOutputStream(new File( output_file ));
        nBitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
        out.flush();
        out.close();

但看起来生成的图像不是我所期望的。如您所见,它有一些线条,我想去掉那些水平的白线。这可能是什么原因造成的?

非常感谢您提供的任何帮助! :)

更新:这里是 CaptureSignature.java 类,“我认为”我遇到了问题:

package com.first.MyApp.drawings;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;

import com.first.Engagia.Camera;
import com.first.Engagia.R;
import com.first.Engagia.R.id;
import com.first.Engagia.R.layout;
import com.first.Engagia.drawings.brush.Brush;
import com.first.Engagia.drawings.brush.CircleBrush;
import com.first.Engagia.drawings.brush.PenBrush;

import java.io.File;
import java.io.FileOutputStream;

public class CaptureSignature extends Activity implements View.OnTouchListener{
    private DrawingSurface drawingSurface;
    private DrawingPath currentDrawingPath;
    private Paint currentPaint;

    private Brush currentBrush;

    private File APP_FILE_PATH = new File(Environment.getExternalStorageDirectory() + "/Engagia/AudienceSignatures");

    //..some other instance variables here

    public static final String LOG_TAG = "-------->>>> CAPTURE SIGNATURE <<<<-------";
    private ProgressDialog mProgressDialog;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.drawing_activity);

        Log.d(LOG_TAG, "Inside capture signature");

        PopIt("Camera", "Please sign on the whitespace provided.");

        Bundle extras = getIntent().getExtras(); 

        if(extras != null){
            this.userId = extras.getString("userId");
            this.appview_username = extras.getString("username");
            this.appview_password = extras.getString("password");

            this.userfirstname = extras.getString("userfirstname");
            this.userlastname = extras.getString("userlastname");
            this.companyname = extras.getString("companyname");

            this.sessionNumber = extras.getString("sessionNumber");
            this.sessionFirstname = extras.getString("sessionFirstname");
            this.sessionLastname = extras.getString("sessionLastname");

            this.AudienceFirstnameLastname = extras.getString("AudienceFirstnameLastname");

        }

        setCurrentPaint();
        currentBrush = new PenBrush();

        drawingSurface = (DrawingSurface) findViewById(R.id.drawingSurface);
        drawingSurface.setOnTouchListener(this);
        drawingSurface.previewPath = new DrawingPath();
        drawingSurface.previewPath.path = new Path();
        drawingSurface.previewPath.paint = getPreviewPaint();


    }

    public void PopIt(String title, String message){
        android.content.DialogInterface.OnClickListener arg1 = null;
        new AlertDialog.Builder(this)
        .setTitle( title )
        .setMessage( message )
        .setPositiveButton("OK", arg1).show();
    }


    private void setCurrentPaint(){
        currentPaint = new Paint();
        currentPaint.setDither(true);
        currentPaint.setColor(0xff000000);
        currentPaint.setStyle(Paint.Style.STROKE);
        currentPaint.setStrokeJoin(Paint.Join.ROUND);
        currentPaint.setStrokeCap(Paint.Cap.ROUND);
        currentPaint.setStrokeWidth(8);

    }

    private Paint getPreviewPaint(){
        final Paint previewPaint = new Paint();
        previewPaint.setColor(0xff000000);
        previewPaint.setStyle(Paint.Style.STROKE);
        previewPaint.setStrokeJoin(Paint.Join.ROUND);
        previewPaint.setStrokeCap(Paint.Cap.ROUND);
        previewPaint.setStrokeWidth(8);
        return previewPaint;
    }




    public boolean onTouch(View view, MotionEvent motionEvent) {
        if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
            drawingSurface.isDrawing = true;

            currentDrawingPath = new DrawingPath();
            currentDrawingPath.paint = currentPaint;
            currentDrawingPath.path = new Path();
            currentBrush.mouseDown(currentDrawingPath.path, motionEvent.getX(), motionEvent.getY());
            currentBrush.mouseDown(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());


        }else if(motionEvent.getAction() == MotionEvent.ACTION_MOVE){
            drawingSurface.isDrawing = true;
            currentBrush.mouseMove( currentDrawingPath.path, motionEvent.getX(), motionEvent.getY() );
            currentBrush.mouseMove(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());


        }else if(motionEvent.getAction() == MotionEvent.ACTION_UP){


            currentBrush.mouseUp(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
            drawingSurface.previewPath.path = new Path();
            drawingSurface.addDrawingPath(currentDrawingPath);

            currentBrush.mouseUp( currentDrawingPath.path, motionEvent.getX(), motionEvent.getY() );

        }

        return true;
    }


    public void onClick(View view){
        switch (view.getId()){
            case R.id.saveBtn:
                Log.d(LOG_TAG, "Save Button clicked!");


                showDialog(0);
                CaptureSignature.this.mProgressDialog.setMessage("Saving your signature...");

                final Activity currentActivity  = this;
                Handler saveHandler = new Handler(){
                    @Override
                    public void handleMessage(Message msg) {
                        final AlertDialog alertDialog = new AlertDialog.Builder(currentActivity).create();
                        alertDialog.setTitle("Done");
                        alertDialog.setMessage("Your signature has been captured.");
                        alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {

                                Log.d(LOG_TAG, "Going to camera activity");

                                //...intent to next activity after signature was taken

                                return;
                            }
                        });

                        if( CaptureSignature.this.mProgressDialog.isShowing() ){
                            dismissDialog(0);
                        }

                        alertDialog.show();
                    }
                } ;
               new ExportBitmapToFile(this,saveHandler, drawingSurface.getBitmap()).execute();
            break;
            case R.id.resetBtn:
                Log.d(LOG_TAG, "Reset Button clicked!");

                //..reset intent here

                break;

        }
    }


    private class ExportBitmapToFile extends AsyncTask<Intent,Void,Boolean> {
        private Context mContext;
        private Handler mHandler;
        private Bitmap nBitmap;

        public ExportBitmapToFile(Context context,Handler handler,Bitmap bitmap) {
            mContext = context;
            nBitmap = bitmap;
            mHandler = handler;
        }

        @Override
        protected Boolean doInBackground(Intent... arg0) {
            try {
                if (!APP_FILE_PATH.exists()) {
                    APP_FILE_PATH.mkdirs();
                }
                Log.d(LOG_TAG, "Sig.output stream area.");

                final FileOutputStream out = new FileOutputStream(new File(APP_FILE_PATH + "/" +  CaptureSignature.this.sessionNumber + ".png"));
                nBitmap.setDensity(50);
                nBitmap.compress(Bitmap.CompressFormat.PNG, 50, out);

                out.flush();
                out.close();

                Log.d(LOG_TAG, "Done bitmap compress.");
                return true;
            }catch (Exception e) {
                e.printStackTrace();
            }

            return false;
        }


        @Override
        protected void onPostExecute(Boolean bool) {
            super.onPostExecute(bool);
            if ( bool ){
                mHandler.sendEmptyMessage(1);
            }
        }
    }

    @Override
    public void onBackPressed() {

    }

    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case 0:
                mProgressDialog = new ProgressDialog(this);
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                mProgressDialog.show();
                return mProgressDialog;
            default:
                return null;
        }
    }
}

基本上,我正在 try catch 用户的签名并将其保存到我的 android 设备 sdcard 中的 png 文件中。

最佳答案

我从未见过我们的 PNG 压缩有这样的问题。不就是原来的位图吗?

关于Android位图压缩不好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7016126/

有关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. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  3. ruby - Ruby 的压缩库? - 2

    是否有任何可用于Ruby的开源压缩/解压库?有没有人实现过LZW?或者,是否有任何使用压缩组件的开源库可以提取出来独立使用?编辑——感谢您的回答!我应该提到我必须压缩的是只驻留在数据库中的长字符串(我不会压缩文件)。此外,如果可以执行此操作的任何库都具有用于客户端压缩/分解的等效JavaScript实现,那将是理想的,因为这将用于Web应用程序。 最佳答案 您会在rubystdlib下找到所有已交付的ruby​​库的一个很好的列表.我会使用zlib库,它是开放的,无处不在,您会发现几乎所有语言的库!

  4. ruby - 读取 zip 存档中的文件,无需解压缩存档 - 2

    我有一个包含100多个zip文件的目录,我需要读取zip文件中的文件以进行一些数据处理,而无需解压缩存档。是否有一个Ruby库可以在不解压缩文件的情况下读取zip存档中的文件内容?使用rubyzip报错:require'zip'Zip::File.open('my_zip.zip')do|zip_file|#Handleentriesonebyonezip_file.eachdo|entry|#Extracttofile/directory/symlinkputs"Extracting#{entry.name}"entry.extract('here')#Readintomemoryc

  5. ruby - 在 Heroku Cedar 上的 Rails 3.2 中,是否有一种标准的方式来提供预压缩的 Assets ? - 2

    我有一个正在HerokuCedar堆栈上部署的Rails3.2应用程序。这意味着应用程序本身负责为其静态Assets提供服务。我希望对这些Assets进行gzip压缩,所以我在production.rb的中间件堆栈中插入了Rack::Deflater:middleware.insert_after('Rack::Cache',Rack::Deflater)...curl告诉我这与宣传的一样有效。但是,由于Heroku将全力运行rakeassets:precompile,生成一堆预gzipAssets,我很想使用它们(而不是让Rack::Deflater再次完成所有工作)。我已经看到使用

  6. Rubyzip 与 native 操作系统压缩 - 2

    我想知道与使用native操作系统库执行压缩相比,使用ruby​​zip压缩数据时的性能差异是什么。我正在从URL获取要压缩的数据,然后使用ZipOutputStream创建zip文件。对于native操作系统实用程序,我正在考虑使用zip工具。很高兴听到这两种方法的优缺点。 最佳答案 事实证明,无论是运算时间还是CPU使用率,都没有太大差异。但是在内存使用方面存在显着差异。与使用ziputil相比,使用ruby​​zip的过程最终会使用更多的内存。在我们的用例中,内存使用是一个重要问题,因此我们最终使用了zip实用程序。

  7. ruby - 如何使用 ruby​​zip 解压缩压缩文件夹 - 2

    我知道如何使用ruby​​zip检索普通zip文件的内容。但是我在解压缩压缩文件夹的内容时遇到了问题,我希望你们中的任何人都能帮助我。这是我用来解压的代码:Zip::ZipFile::open(@file_location)do|zip|zip.eachdo|entry|nextifentry.name=~/__MACOSX/orentry.name=~/\.DS_Store/or!entry.file?logger.debug"#{entry.name}"@data=File.new("#{Rails.root.to_s}/tmp/#{entry.name}")endendentry

  8. ruby-on-rails - 下载和解压缩 Rake 任务 - 2

    我想每周更新一个城市表以反射(reflect)世界各地城市的变化。为此,我正在创建一个Rake任务。如果可能,我希望在不添加其他gem依赖项的情况下执行此操作。压缩文件是在geonames.org/15000cities.zip上公开可用的压缩文件.我的尝试:require'net/http'require'zip'namespace:geocitiesdodesc"RaketasktofetchGeocitiescitylistevery3days"task:fetchdouri=URI('http://download.geonames.org/export/dump/cities

  9. ruby-on-rails - 在 Rails 中,将散列压缩为嵌套散列的最佳方法是什么 - 2

    假设我有这个:[{:user_id=>1,:search_id=>a},{:user_id=>1,:search_id=>b},{:user_id=>2,:search_id=>c},{:user_id=>2,:search_id=>d}]我想结束:[{:user_id=>1,:search_id=>[a,b]},{:user_id=>2,:search_id=>[c,d]}]最好的方法是什么? 最佳答案 确实是非常奇怪的要求。无论如何[{:user_id=>1,:search_id=>"a"},{:user_id=>1,:sear

  10. ruby-on-rails - 留下未使用的 REST 操作不好吗? - 2

    我真的很困惑如何做到这一点。我也感到疲倦和沮丧,我的大脑因看到这么多不同的东西而受伤。保留未使用的REST操作是一种不好的做法吗?例如,我有一个资源模型,用户可以提交它们,但我不需要“索引”操作来显示它们,因为这是由Home#indexController处理的。我想要做的就是使用link_to转到带有表单的页面以添加新资源。所以现在我尝试做的所有link_to都在我做resources_path时继续尝试去/resources。我阅读了如何使用“遗留”方法并直接链接到Controller中的操作,但这不是“rails方式”。现在,如果我不使用默认情况下执行的所有不同REST操作,我将

随机推荐