1

I am using canvas for modifying my image. However, I am having a problem. If I use options.inSampleSize = 4; the image becomes too small and the quality degrades. However, if I don't give, it overflows from memory and gives an error.

    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);

// Bitmap 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());
        }
    }

Here is my current Error Log.

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

The commented part shows a couple of things more I tried. Also I tried

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

But it makes my whole Image black and drawing on it does not effect the canvas, it remains black.

Bhavya Arora
  • 768
  • 3
  • 16
  • 35

2 Answers2

0
  1. Do not create a bitmap with full height and width. Try to reduce the height or width without affecting the aspect ratio.
  2. If inSampleSize = 4 is reducing clarity, go for something less than that.
  3. Why are you creating another bitmap scaledBitmap? If you really want to create a scaled bitmap, try Bitmap.createScaledBitmap().
  4. Don't forget to call Bitmap.recycle() once you don't need a bitmap.

For more detailed info on the above points read here: https://stackoverflow.com/a/33394336/4747587

UPDATE: The crash happened not because of BitmapFactory.decodeFile(), but because of the below line of code:

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

Replace this with:

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

So, play around with the 1.5f value here to one that suits you. You are trying to create a bitmap the same size as the screen with full resolution. That would take huge memory. Instead you need to create a smaller image. All this is well documented in the above link.

Community
  • 1
  • 1
Henry
  • 17,490
  • 7
  • 63
  • 98
  • though all the examples state to use options.inScaled, but I did not get the desired result even with using that. :( The image still reduces it size. I just want a bare minimum code that does not reduce the size of the image upon editing. The recycle() helps to avoid Out of Memory exception. – Bhavya Arora Nov 09 '15 at 19:03
  • Updated my answer.. Try to create a scaled bitmap with less width and height. Also call `original1.recycle()` after creating the `scaledBitmap` – Henry Nov 10 '15 at 05:55
0

If you really want to modify your image you can do it at run time. Using this link you will find more details .

Quality problems when resizing an image at runtime

But, there is another way to stop 'bad image quality after your resizing or scaling your bitmap . You can Disable scaling on bitmap load from resources using:

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

Also As #Henry Suggested you can use :

 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

Community
  • 1
  • 1
RKosamia
  • 181
  • 7
  • though all the examples state to use options.inScaled, but I did not get the desired result even with using that. :( The image still reduces it size. I just want a bare minimum code that does not reduce the size of the image upon editing. The recycle() helps to avoid Out of Memory exception. – Bhavya Arora Nov 09 '15 at 17:33