【问题标题】:Canvas Reducing Image Quality Android画布降低图像质量 Android
【发布时间】:2016-02-09 20:39:27
【问题描述】:

我正在使用画布来修改我的图像。但是,我遇到了问题。如果我使用 options.inSampleSize = 4;图像变得太小并且质量下降。但是,如果我不给,它会从内存中溢出并给出错误。

    protected void onDraw(Canvas canvas) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inSampleSize = 1;//Tried 4-But image quality too low


        Bitmap original1 = BitmapFactory.decodeFile(imagePathF, options);

      int width = original1.getWidth();
        int height = original1.getHeight();
        int bounding = dpToPx(Math.round(height));


        float xScale = ((float) bounding) / width2;
        float yScale = ((float) bounding) / height2;
        float scale = (xScale <= yScale) ? xScale : yScale;


        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);


        Bitmap scaledBitmap = Bitmap.createBitmap(original1, 0, 0, width, height, matrix, true);

          Paint paint = new Paint();
        paint.setColor(Color.BLACK); // Text Color
        //Paint alphaChannel = new Paint();
        //alphaChannel.setAlpha(100);
        paint.setAlpha(100);
        paint.setTextSize(20 * scale);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); // Text Overlapping Pattern
        paint.setFlags(Paint.ANTI_ALIAS_FLAG);

        paint.getTextBounds(gText, 0, gText.length(), bounds);
        Typeface font = Typeface.createFromAsset(getAssets(), "Chantelli_Antiqua.ttf");
        paint.setTypeface(font);

        int x = (width2)/2;
        //int y = Math.round(height1)+(Math.round(height1) - Math.round(height2) / 2);
        int y = Math.round(height);
        int yOffset=calcYoff(gText, 0, 0, paint, canvas, Math.round(20 * scale), width);

// 位图 scaledBitmap = Bitmap.createBitmap(original1, 0, 0, width, height, matrix, true);

              mDrawable = new BitmapDrawable(res, scaledBitmap);//original1);//
          canvas.drawColor(Color.TRANSPARENT);
            //canvas.drawBitmap(resizedBitmap, 0, 0, paint);
            mDrawable.draw(canvas);


            getDrawingCache().compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(imagePathF)));



            super.onDraw(canvas);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (Exception e) {
            Log.e("Error--------->", e.toString());
        }
    }

这是我当前的错误日志。

11-09 03:21:56.849 12345-12345/com.example.chkee.appfront E/AndroidRuntime: 致命异常: main 进程:com.example.chkee.appfront,PID:12345 java.lang.IllegalArgumentException:位图大小超过 32 位 在 android.graphics.Bitmap.nativeCreate(Native Method) 在 android.graphics.Bitmap.createBitmap(Bitmap.java:812) 在 android.graphics.Bitmap.createBitmap(Bitmap.java:789) 在 android.graphics.Bitmap.createBitmap(Bitmap.java:720) 在 com.example.chkee.ScrapBook.AddNotes$Draw2d.onDraw(AddNotes.java:288) 在 android.view.View.draw(View.java:15247) 在 android.view.View.updateDisplayListIfDirty(View.java:14183) 在 android.view.View.getDisplayList(View.java:14205) 在 android.view.View.draw(View.java:14975) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3406) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199) 在 android.view.View.updateDisplayListIfDirty(View.java:14178) 在 android.view.View.getDisplayList(View.java:14205) 在 android.view.View.draw(View.java:14975) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3406) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199) 在 android.view.View.updateDisplayListIfDirty(View.java:14178) 在 android.view.View.getDisplayList(View.java:14205) 在 android.view.View.draw(View.java:14975) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3406) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199) 在 android.view.View.updateDisplayListIfDirty(View.java:14178) 在 android.view.View.getDisplayList(View.java:14205) 在 android.view.View.draw(View.java:14975) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3406) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199) 在 android.view.View.updateDisplayListIfDirty(View.java:14178) 在 android.view.View.getDisplayList(View.java:14205) 在 android.view.View.draw(View.java:14975) 在 android.view.ViewGroup.drawChild(ViewGroup.java:3406) 在 android.view.ViewGroup.dispatchDraw(ViewGroup.java:3199) 在 android.view.View.draw(View.java:15250) 在 android.widget.FrameLayout.draw(FrameLayout.java:598) 在 com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2906) 在 android.view.View.updateDisplayListIfDirty(View.java:14183) 在 android.view.View.getDisplayList(View.java:14205) 在 android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:273) 在 android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:279) 在 android.view.ThreadedRenderer.draw(ThreadedRenderer.java:318) 在 android.view.ViewRootImpl.draw(ViewRootImpl.java:2536) 在 android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2352) 在 android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1982) 在 android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061) 在 android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5891) 在 android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) 在 android.view.Choreographer.doCallbacks(Choreographer.java:580) 在 android.view.Choreographer.doFrame(Choreographer.java:550) 在 android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) 在 android.os.Handler.handleCallback(Handler.java:739) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:135) 在 android.app.ActivityThread.main(ActivityThread.java:5292) 在 java.lang.reflect.Method.invoke(本机方法) 在 java.lang.reflect.Method.invoke(Method.java:372) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)

评论部分显示了我尝试的更多内容。 我也试过了

Bitmap mBackgroundImage = Bitmap.createBitmap(Size, Size,
                Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBackgroundImage);

但它使我的整个图像变黑并且在其上绘图不会影响画布,它仍然是黑色的。

【问题讨论】:

    标签: android canvas bitmap bitmapfactory


    【解决方案1】:

    如果您真的想修改图像,可以在运行时进行。使用此链接,您将找到更多详细信息。

    Quality problems when resizing an image at runtime

    但是,在调整位图大小或缩放位图后,还有另一种方法可以阻止“糟糕的图像质量”。您可以使用以下方法禁用从资源加载位图的缩放:

    Options options = new BitmapFactory.Options();
        options.inScaled = false;
        Bitmap source = BitmapFactory.decodeResource(a.getResources(), path, options);
    

    也作为 #Henry 建议您可以使用:

     Bitmap resizedBitmap = Bitmap.createScaledBitmap(originalBitmap, newWidth, newHeight, false); 
    

    How to get scaled bitmap with respect to screen size with out getting Out of memory exception

    【讨论】:

    • 虽然所有示例都声明使用 options.inScaled,但即使使用它我也没有得到想要的结果。 :( 图像仍然减小了它的大小。我只想要一个在编辑时不会减小图像大小的最小代码。recycle() 有助于避免内存不足异常。
    【解决方案2】:
    1. 不要使用完整的heightwidth 创建位图。尝试在不影响纵横比的情况下减小高度或宽度。
    2. 如果 inSampleSize = 4 会降低清晰度,请选择比这更低的值。
    3. 为什么要创建另一个位图scaledBitmap?如果你真的想创建一个缩放位图,试试Bitmap.createScaledBitmap()
    4. 如果您不需要bitmap,请不要忘记致电Bitmap.recycle()

    有关上述要点的更多详细信息,请阅读此处:https://stackoverflow.com/a/33394336/4747587

    更新:崩溃不是因为BitmapFactory.decodeFile(),而是因为下面这行代码:

     Bitmap scaledBitmap = Bitmap.createBitmap(original1, 0, 0, width, height, matrix, true);
    

    将其替换为:

     Bitmap scaledBitmap= Bitmap.createScaledBitmap(original1, (int)(width/1.5f), (int)(height/1.5f), false); 
    

    因此,请在此处使用 1.5f 值来选择适合您的值。您正在尝试创建一个与全分辨率屏幕大小相同的bitmap。那将占用大量内存。相反,您需要创建一个较小的图像。所有这些都在上面的链接中有很好的记录。

    【讨论】:

    • 尽管所有示例都声明使用 options.inScaled,但即使使用它我也没有得到想要的结果。 :( 图像仍然减小了它的大小。我只想要一个在编辑时不会减小图像大小的最小代码。recycle() 有助于避免内存不足异常。
    • 更新了我的答案。尝试创建一个宽度和高度较小的缩放位图。在创建 scaledBitmap 后也调用 original1.recycle()
    猜你喜欢
    • 1970-01-01
    • 2014-08-10
    • 1970-01-01
    • 2019-08-23
    • 2017-08-03
    • 1970-01-01
    • 1970-01-01
    • 2016-06-06
    • 2010-11-12
    相关资源
    最近更新 更多