No se puede guardar el mapa de bits modificado (saturación modificada)

I got a problem, where I am stuck now for a long time, I hope you guys can help me out. I got a piece of code that I can open an image, change the saturation (with seekbar). then I want to save the changed image. But that last part isn't working as it should be.

With this code, I can change saturation, and then save the changed bitmap, but it saves the bitmap with the size of the ImageView (480 x 517) however he does apply the saturation change (that is good)

ColorMatrix cm = new ColorMatrix();

System.out.println(progress2);
cm.setSaturation(progress2);
ColorFilter = new ColorMatrixColorFilter(cm);
bitmap_image = BitmapFactory.decodeFile(filePath);
ImageView img = (ImageView) findViewById(R.id.gallery1);
img.setColorFilter(ColorFilter);
img.setImageBitmap(bitmap_image);
img.buildDrawingCache(true);
img.setDrawingCacheEnabled(true);
Bitmap b = img.getDrawingCache();


Bitmap resizedBitmap = Bitmap.createBitmap(bitmap_image, 0, 0, 3264, 2448);
File file = new File(sdcard+"/DCIM/Camera/image3.jpg");
try {
    file.createNewFile();
    FileOutputStream ostream = new FileOutputStream(file);
    **b.compress(CompressFormat.JPEG, 100, ostream);**
    ostream.close();
} catch (Exception e) 
            {
            System.out.println("WRITING HAS FAILED");
            e.printStackTrace();
            }

And the next code, I can also change the saturation, but when I save the bitmap, it does save the bitmap with the original height and width (3264 x 2448) but it doesn't save the saturation change.

   ColorMatrix cm = new ColorMatrix();

System.out.println(progress2);
cm.setSaturation(progress2);
ColorFilter = new ColorMatrixColorFilter(cm);
bitmap_image = BitmapFactory.decodeFile(filePath);
ImageView img = (ImageView) findViewById(R.id.gallery1);
img.setColorFilter(ColorFilter);
img.setImageBitmap(bitmap_image);
img.buildDrawingCache(true);
img.setDrawingCacheEnabled(true);
Bitmap b = img.getDrawingCache();


Bitmap resizedBitmap = Bitmap.createBitmap(bitmap_image, 0, 0, 3264, 2448);
File file = new File(sdcard+"/DCIM/Camera/image3.jpg");
try {
    file.createNewFile();
    FileOutputStream ostream = new FileOutputStream(file);
    **resizedBitmap.compress(CompressFormat.JPEG, 100, ostream);**
    ostream.close();
    } catch (Exception e) 
        {
        System.out.println("WRITING HAS FAILED");
        e.printStackTrace();
        }

But what I need is that it saves the saturation changes (code 1) and keeps the original width - height (code 2), but somehow I don't seem to get those 2 codes work together.

Please put me in the good direction. Code is maybe a mess, tried a lot of things and the structure isn't getting better of it.

**code** that is the line that changed.

EDIT: When I do this: (suggestion of Ricki)

Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, 3264, 2448);

I get this error log:

03-09 15:03:02.880: E/AndroidRuntime(847): FATAL EXCEPTION: main
03-09 15:03:02.880: E/AndroidRuntime(847): java.lang.NullPointerException
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.graphics.Bitmap.createBitmap(Bitmap.java:409)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.graphics.Bitmap.createBitmap(Bitmap.java:383)
03-09 15:03:02.880: E/AndroidRuntime(847):  at com.dlv.groenmeter.GroenMeterActivity$13.onStopTrackingTouch(GroenMeterActivity.java:937)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.widget.SeekBar.onStopTrackingTouch(SeekBar.java:115)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.widget.AbsSeekBar.onTouchEvent(AbsSeekBar.java:303)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.view.View.dispatchTouchEvent(View.java:3938)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:942)
03-09 15:03:02.880: E/AndroidRuntime(847):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1730)
03-09 15:03:02.880: E/AndroidRuntime(847):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1142)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.app.Activity.dispatchTouchEvent(Activity.java:2102)
03-09 15:03:02.880: E/AndroidRuntime(847):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1714)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.view.ViewRoot.deliverPointerEvent(ViewRoot.java:2218)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1889)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.os.Handler.dispatchMessage(Handler.java:99)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.os.Looper.loop(Looper.java:123)
03-09 15:03:02.880: E/AndroidRuntime(847):  at android.app.ActivityThread.main(ActivityThread.java:3691)
03-09 15:03:02.880: E/AndroidRuntime(847):  at java.lang.reflect.Method.invokeNative(Native Method)
03-09 15:03:02.880: E/AndroidRuntime(847):  at java.lang.reflect.Method.invoke(Method.java:507)
03-09 15:03:02.880: E/AndroidRuntime(847):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:847)
03-09 15:03:02.880: E/AndroidRuntime(847):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:605)
03-09 15:03:02.880: E/AndroidRuntime(847):  at dalvik.system.NativeStart.main(Native Method)

preguntado el 09 de marzo de 12 a las 13:03

7th line from under (marked with 'código') that is the only change, rest of the code is the same idd, but it should give better perspective of what I do. -

2 Respuestas

There are 2 problems with the 2nd code:

1) Your saturated image is b so resizedBitmap should be created from that like this:

Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, 3264, 2448);

2) You enable DrawingCache after you build:

img.buildDrawingCache(true);
img.setDrawingCacheEnabled(true);

It should be in reverse order:

img.setDrawingCacheEnabled(true);
img.buildDrawingCache(true);

EDIT:

Try this code to set the saturation:

    Bitmap bmp = BitmapFactory.decodeFile(filePath);
    Bitmap alteredBitmap = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());
    Canvas canvas = new Canvas(alteredBitmap);
    Paint paint = new Paint();
    ColorMatrix cm = new ColorMatrix();
    cm.setSaturation(progress2);
    paint.setColorFilter(new ColorMatrixColorFilter(cm));
    Matrix matrix = new Matrix();
    canvas.drawBitmap(bmp, matrix, paint);

Bitmap resizedBitmap = Bitmap.createBitmap(alteredBitmap, 0, 0, 3264, 2448);
File file = new File(sdcard+"/DCIM/Camera/image3.jpg");
try {
    file.createNewFile();
    FileOutputStream ostream = new FileOutputStream(file);
    resizedBitmap.compress(CompressFormat.JPEG, 100, ostream);
    ostream.close();
    } catch (Exception e) 
        {
        System.out.println("WRITING HAS FAILED");
        e.printStackTrace();
        }

respondido 09 mar '12, 14:03

1) causes same error on the logcat that I posted above, no idea why it says 'b' is 'null', because 1st code of mine does work (where I use 'b') 2) Changed this too, thanks for this already :) - flujo grande

Significa b is null and 1st code works because b is never used there. I think your saturation change code doesnt work. Are you really sure it works in #1? - Caner

From what I can see the variable 'b' contains the saturated image. It looks like you should change the line

Bitmap resizedBitmap = Bitmap.createBitmap(bitmap_image, 0, 0, 3264, 2448);

A:

Bitmap resizedBitmap = Bitmap.createBitmap(b, 0, 0, 3264, 2448);

Eso funciona para ti?

respondido 09 mar '12, 13:03

Yes idd, I thought that too, but then it saves an image of 0kb (empty). So soemthing is still wrong - flujo grande

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.