How to programmatically change contrast of a bitmap in android?

空扰寡人 提交于 2019-12-28 03:38:13

问题


I want to programmatically change the contrast of bitmap. Till now I have tried this.

private Bitmap adjustedContrast(Bitmap src, double value)
    {
        // image size
        int width = src.getWidth();
        int height = src.getHeight();
        // create output bitmap
        Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());
        // color information
        int A, R, G, B;
        int pixel;
        // get contrast value
        double contrast = Math.pow((100 + value) / 100, 2);

        // scan through all pixels
        for(int x = 0; x < width; ++x) {
            for(int y = 0; y < height; ++y) {
                // get pixel color
                pixel = src.getPixel(x, y);
                A = Color.alpha(pixel);
                // apply filter contrast for every channel R, G, B
                R = Color.red(pixel);
                R = (int)(((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
                if(R < 0) { R = 0; }
                else if(R > 255) { R = 255; }

                G = Color.green(pixel);
                G = (int)(((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
                if(G < 0) { G = 0; }
                else if(G > 255) { G = 255; }

                B = Color.blue(pixel);
                B = (int)(((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
                if(B < 0) { B = 0; }
                else if(B > 255) { B = 255; }

                // set new pixel color to output bitmap
                bmOut.setPixel(x, y, Color.argb(A, R, G, B));
            }
        }
        return bmOut;
    }

But this does not work as expected. Please help me in this or provide any other solution to achieve this. Thanks in advance.


回答1:


Try this. Your code didn't work because you create only a mutable bitmap and didn't copy the image of source bitmap to the mutable one if i'm not mistaken.

Hope It helps :)

private Bitmap adjustedContrast(Bitmap src, double value)
{
    // image size
    int width = src.getWidth();
    int height = src.getHeight();
    // create output bitmap

    // create a mutable empty bitmap
    Bitmap bmOut = Bitmap.createBitmap(width, height, src.getConfig());

    // create a canvas so that we can draw the bmOut Bitmap from source bitmap
    Canvas c = new Canvas();
    c.setBitmap(bmOut);

    // draw bitmap to bmOut from src bitmap so we can modify it
    c.drawBitmap(src, 0, 0, new Paint(Color.BLACK));


    // color information
    int A, R, G, B;
    int pixel;
    // get contrast value
    double contrast = Math.pow((100 + value) / 100, 2);

    // scan through all pixels
    for(int x = 0; x < width; ++x) {
        for(int y = 0; y < height; ++y) {
            // get pixel color
            pixel = src.getPixel(x, y);
            A = Color.alpha(pixel);
            // apply filter contrast for every channel R, G, B
            R = Color.red(pixel);
            R = (int)(((((R / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
            if(R < 0) { R = 0; }
            else if(R > 255) { R = 255; }

            G = Color.green(pixel);
            G = (int)(((((G / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
            if(G < 0) { G = 0; }
            else if(G > 255) { G = 255; }

            B = Color.blue(pixel);
            B = (int)(((((B / 255.0) - 0.5) * contrast) + 0.5) * 255.0);
            if(B < 0) { B = 0; }
            else if(B > 255) { B = 255; }

            // set new pixel color to output bitmap
            bmOut.setPixel(x, y, Color.argb(A, R, G, B));
        }
    }
    return bmOut;
}



回答2:


Here is complete method:

/**
 * 
 * @param bmp input bitmap
 * @param contrast 0..10 1 is default
 * @param brightness -255..255 0 is default
 * @return new bitmap
 */
public static Bitmap changeBitmapContrastBrightness(Bitmap bmp, float contrast, float brightness)
{
    ColorMatrix cm = new ColorMatrix(new float[]
            {
                contrast, 0, 0, 0, brightness,
                0, contrast, 0, 0, brightness,
                0, 0, contrast, 0, brightness,
                0, 0, 0, 1, 0
            });

    Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());

    Canvas canvas = new Canvas(ret);

    Paint paint = new Paint();
    paint.setColorFilter(new ColorMatrixColorFilter(cm));
    canvas.drawBitmap(bmp, 0, 0, paint);

    return ret;
}



回答3:


We can use seek bar to adjust contrast.

MainActivity.java:

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    ImageView imageView;
    SeekBar seekbar;
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = (ImageView) findViewById(R.id.image);
        textView = (TextView) findViewById(R.id.label);

        seekbar = (SeekBar) findViewById(R.id.seekbar);
        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
                imageView.setImageBitmap(changeBitmapContrastBrightness(BitmapFactory.decodeResource(getResources(), R.drawable.lhota), (float) progress / 100f, 1));
                textView.setText("Contrast: "+(float) progress / 100f);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {}

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });

        seekbar.setMax(200);
        seekbar.setProgress(100);
    }

    public static Bitmap changeBitmapContrastBrightness(Bitmap bmp, float contrast, float brightness) {
        ColorMatrix cm = new ColorMatrix(new float[]
                {
                        contrast, 0, 0, 0, brightness,
                        0, contrast, 0, 0, brightness,
                        0, 0, contrast, 0, brightness,
                        0, 0, 0, 1, 0
                });

        Bitmap ret = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), bmp.getConfig());

        Canvas canvas = new Canvas(ret);

        Paint paint = new Paint();
        paint.setColorFilter(new ColorMatrixColorFilter(cm));
        canvas.drawBitmap(bmp, 0, 0, paint);

        return ret;
    }
}

activity_main.java:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/label"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"
        android:textAppearance="@android:style/TextAppearance.Holo.Medium" />

    <SeekBar
        android:id="@+id/seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>



回答4:


Here is a Renderscript implementation (from the Gradle Example Projects)

ip.rsh

#pragma version(1)
#pragma rs java_package_name(your.app.package)

contrast.rs

#include "ip.rsh"

static float brightM = 0.f;
static float brightC = 0.f;

void setBright(float v) {
    brightM = pow(2.f, v / 100.f);
    brightC = 127.f - brightM * 127.f;
}

void contrast(const uchar4 *in, uchar4 *out)
{
#if 0
    out->r = rsClamp((int)(brightM * in->r + brightC), 0, 255);
    out->g = rsClamp((int)(brightM * in->g + brightC), 0, 255);
    out->b = rsClamp((int)(brightM * in->b + brightC), 0, 255);
#else
    float3 v = convert_float3(in->rgb) * brightM + brightC;
    out->rgb = convert_uchar3(clamp(v, 0.f, 255.f));
#endif
}

Java

private Bitmap changeBrightness(Bitmap original RenderScript rs) {
    Allocation input = Allocation.createFromBitmap(rs, original);
    final Allocation output = Allocation.createTyped(rs, input.getType());
    ScriptC_contrast mScript = new ScriptC_contrast(rs);
    mScript.invoke_setBright(50.f);
    mScript.forEach_contrast(input, output);
    output.copyTo(original);
    return original;
}



回答5:


I just had the same problem and ended up using the Color Matrix that Ruslan Yanchyshyn describes. I needed to automatically adjust brightness depending on the image, so I used BoofCV to create a histogram from a scaled version of the image - It took way to long to process the whole image. Then I analyzed the histogram - looked at what was the darkest and brightest colors and then created a color matrix which transforms the colors so the darkest colors are 0 and the brightest colors are 255. In this way the new image uses the whole spectrum from dark/black to light/white now.

Ended up writing a small post on how I did it on our company blog here if anyone are interested. http://appdictive.dk/blog/projects/2016/07/26/levels_with_color_matrix/




回答6:


Maybe you can try this one:

http://xjaphx.wordpress.com/2011/06/21/image-processing-contrast-image-on-the-fly/

Hope that helps! :)




回答7:


http://android.okhelp.cz/bitmap-set-contrast-and-brightness-android/

have a look at this ,this might solve your problem




回答8:


Assumption - ImageView is used to display the bitmap

I did a more enhancement in the Ruslan's answer

Instead of replacing bitmap every time (which makes it slow if you are using seek bar) we can work on the Color Filter of the ImageView.

float contrast;
float brightness = 0;
ImageView imageView;

// SeekBar ranges from 0 to 90
// contrast ranges from 1 to 10  
mSeekBarContrast.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            contrast = (float) (i + 10) / 10;
            // Changing the contrast of the bitmap
            imageView.setColorFilter(getContrastBrightnessFilter(contrast,brightness));
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
});

ColorMatrixColorFilter getContrastBrightnessFilter(float contrast, float brightness) {
    ColorMatrix cm = new ColorMatrix(new float[]
            {
                    contrast, 0, 0, 0, brightness,
                    0, contrast, 0, 0, brightness,
                    0, 0, contrast, 0, brightness,
                    0, 0, 0, 1, 0
            });
    return new ColorMatrixColorFilter(cm);
}

P.S - Brightness can also be changed along with contrast using this method



来源:https://stackoverflow.com/questions/12891520/how-to-programmatically-change-contrast-of-a-bitmap-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!