web-dev-qa-db-fra.com

Comment changer le contraste d'un bitmap par programme sous Android?

Je veux modifier par programme le contraste du bitmap. Jusqu'à présent, j'ai essayé cela.

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

Mais cela ne fonctionne pas comme prévu. S'il vous plaît, aidez-moi ou fournissez toute autre solution pour y parvenir. Merci d'avance.

19
Sanchit Paurush

Essaye ça. Votre code n'a pas fonctionné parce que vous créez uniquement un bitmap mutable et n'avez pas copié l'image du bitmap source vers le mutable si je ne me trompe pas.

J'espère que ça aide :)

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;
}
21
user948620

Voici la méthode complète:

/**
 * 
 * @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;
}
49
Ruslan Yanchyshyn

On peut utiliser seek bar pour régler le contraste.

enter image description here

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>
6
Stephen

Voici une implémentation de Renderscript ( à partir des exemples de projets Gradle )

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
patrickf

J'ai juste eu le même problème et j'ai fini par utiliser le Color Matrix que Ruslan Yanchyshyn décrit. J'avais besoin d'ajuster automatiquement la luminosité en fonction de l'image, j'ai donc utilisé BoofCV pour créer un histogramme à partir d'une version mise à l'échelle de l'image - Il a fallu beaucoup de temps pour traiter l'image entière. Ensuite, j'ai analysé l'histogramme - j'ai regardé quelles étaient les couleurs les plus sombres et les plus lumineuses, puis j'ai créé une matrice de couleurs qui transforme les couleurs de sorte que les couleurs les plus sombres sont 0 et les couleurs les plus brillantes sont 255. De cette façon, la nouvelle image utilise tout le spectre de l'obscurité/noir à clair/blanc maintenant.

J'ai fini par écrire un petit article sur la façon dont je l'ai fait sur le blog de notre entreprise ici si quelqu'un est intéressé. http://appdictive.dk/blog/projects/2016/07/26/levels_with_color_matrix/

2
tobalr

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

jetez un oeil à cela, cela pourrait résoudre votre problème

1
Amit Hooda

Vous pouvez peut-être essayer celui-ci:

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

J'espère que cela pourra aider! :)

1
kdroider

Hypothèse - ImageView est utilisé pour afficher le bitmap

J'ai fait une amélioration supplémentaire dans la réponse du Ruslan

Au lieu de remplacer bitmap à chaque fois (ce qui le rend lent si vous utilisez la barre de recherche), nous pouvons travailler sur le Filtre couleur de l'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 - La luminosité peut également être modifiée avec le contraste en utilisant cette méthode

1
Palkesh Jain