Introducción al procesamiento de imágenes de Android (activado) -transformación de color de la imagen

Dividiré esta serie en dos partes para explicar el conocimiento introductorio de la transformación del color de la imagen y la transformación de la forma de la imagen en Android.

Modelo RGBA

RGBA es una abreviatura y sus significados son Red, Green, Blue, Aplha. Es decir, los tres colores primarios de rojo, verde y azul y las cuatro opciones de transparencia. Los distintos colores que solemos ver son solo los tres colores primarios mezclados en diferentes proporciones, y alfa puede controlar la transparencia de la imagen.

A continuación, se muestran tres conceptos importantes en el procesamiento de imágenes:

  • Matiz / matiz: el color transmitido por el objeto.
  • Saturación: la pureza del color, del 0% (gris) al 100% (saturado) para describir
  • Brillo / Claridad: la claridad y oscuridad relativas del color.

En Android, el sistema proporciona la clase ColorMatrix para ayudar a ajustar los tres atributos importantes de la imagen.

tono

Establezca el tono de toda la imagen mediante el método setRotate. El primero es el color que debe establecerse, donde 0 corresponde a R, 1 corresponde a G y 2 corresponde a B. Aquí por simplicidad, establezca el mismo valor de tono.

ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0,hue);     //R
hueMatrix.setRotate(1,hue);     //G
hueMatrix.setRotate(2,hue);     //B

saturación

Establezca la saturación de la imagen mediante el método setSaturation. Al establecer el valor, puede controlar la saturación de la imagen.

ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);

brillo

Configure el brillo de la imagen mediante el método setScale. Los cuatro parámetros son brillo R, brillo G, brillo B y brillo de transparencia.

ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum,lum,lum,1);

Ajuste el efecto de la imagen mediante el método ColorMatrix

A continuación, cree un proyecto de Android para comenzar a aprender a usar el procesamiento de imágenes.

Interfaz principal

Primero, cree un menú principal para seleccionar la modificación de la imagen.

activity_main.xml

<?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:padding="16dp"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="40dp"
        android:textSize="40sp"
        android:text="美图秀秀"/>

    <Button
        android:id="@+id/btn_primary_color"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="PRIMARY COLOR"/>

    <Button
        android:id="@+id/btn_color_matrix"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="COLOR MATRIX"/>

    <Button
        android:id="@+id/btn_3"
           android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="等待实现"/>
</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private Button primaryButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        primaryButton = (Button)findViewById(R.id.btn_primary_color);
        primaryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                primaryColorEvent();
            }
        });
    }

    public void primaryColorEvent(){
        Intent intent = new Intent(MainActivity.this,PrimaryColorActivity.class);
        startActivity(intent);
    }
}

Interfaz de ajuste de tres colores primarios

Puede analizarlo aproximadamente. Si desea ajustar una imagen, debe seguir estos tres pasos:

  1. Obtener una foto
  2. Realiza una serie de modificaciones a la imagen.
  3. Devolver una foto

Por lo tanto, también puede diseñar una clase de herramienta para realizar el procesamiento relacionado con la imagen, lo que puede mejorar la reutilización del código.

public class ImageUtils {
    public static Bitmap handleImageEffect(Bitmap bitmap,float hue,float saturation,float lum){
        //由于不能直接在原图上修改,所以创建一个图片,设定宽度高度与原图相同。为32位ARGB图片
        Bitmap currentBitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        //创建一个和原图相同大小的画布
        Canvas canvas = new Canvas(currentBitmap);
        //创建笔刷并设置抗锯齿
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //色相ColorMatrix
        ColorMatrix hueMatrix = new ColorMatrix();
        hueMatrix.setRotate(0,hue);
        hueMatrix.setRotate(1,hue);
        hueMatrix.setRotate(2,hue);
        //饱和度ColorMatrix
        ColorMatrix saturationMatrix = new ColorMatrix();
        saturationMatrix.setSaturation(saturation);
        //亮度ColorMatrix
        ColorMatrix lumMatrix = new ColorMatrix();
        lumMatrix.setScale(lum,lum,lum,1);
        //将三种效果融合起来
        ColorMatrix imageMatrix = new ColorMatrix();
        imageMatrix.postConcat(hueMatrix);
        imageMatrix.postConcat(saturationMatrix);
        imageMatrix.postConcat(lumMatrix);

        paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
        canvas.drawBitmap(bitmap,0,0,paint);

        return currentBitmap;
    }
}

Aquí, se utiliza la clase Canvas. La clase canvas es una clase canvas, y las operaciones posteriores se realizarán en el lienzo en lugar de en la imagen original. Se establecieron tres ColorMatrix, se llevaron a cabo diferentes aspectos de la operación y se utilizó el método postConcat para fusionar estos Matrix. Modifique las propiedades relevantes de la pintura mediante el método setColorFilter y luego dibuje la imagen en el lienzo. Finalmente, devuelva la imagen modificada.

De vuelta a nuestra interfaz. El diseño utiliza tres barras de búsqueda para controlar los tres atributos de tono, saturación y brillo, respectivamente.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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_view"
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:scaleType="centerCrop"
        android:layout_marginTop="24dp"
        android:layout_marginBottom="24dp"
        android:layout_centerHorizontal="true"/>

    <SeekBar
        android:id="@+id/seekbar_hue"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:layout_below="@id/image_view"/>

    <SeekBar
        android:id="@+id/seekbar_saturation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
          android:layout_margin="10dp"
        android:layout_below="@id/seekbar_hue"/>

    <SeekBar
        android:id="@+id/seekbar_lum"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
           android:layout_below="@id/seekbar_saturation"/>
</RelativeLayout>

Luego edite PrimaryColorActivity. Aquí definimos un valor máximo y un valor intermedio, que se puede cambiar del valor intermedio, y luego obtenemos los valores de tono, saturación y brillo a través de una serie de métodos.

public class PrimaryColorActivity extends AppCompatActivity implements SeekBar.OnSeekBarChangeListener{
    private ImageView mImageView;
    private SeekBar mSeekbarHue,mSeekbarSaturation,mSeekbarLum;
    private final static int MAX_VALUE = 255;   //最大值
    private final static int MID_VALUE = 127;   //中间值

    private float mHue,mSaturation,mLum;

    private Bitmap bitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_primary_color);

        //获取图片
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test1);

        mImageView = (ImageView)findViewById(R.id.image_view);

        mImageView.setImageBitmap(bitmap);

        mSeekbarHue = (SeekBar)findViewById(R.id.seekbar_hue);
        mSeekbarSaturation = (SeekBar)findViewById(R.id.seekbar_saturation);
        mSeekbarLum = (SeekBar)findViewById(R.id.seekbar_lum);

        mSeekbarHue.setOnSeekBarChangeListener(this);
        mSeekbarSaturation.setOnSeekBarChangeListener(this);
        mSeekbarLum.setOnSeekBarChangeListener(this);

        mSeekbarHue.setMax(MAX_VALUE);
        mSeekbarSaturation.setMax(MAX_VALUE);
        mSeekbarLum.setMax(MAX_VALUE);

        mSeekbarHue.setProgress(MID_VALUE);
        mSeekbarSaturation.setProgress(MID_VALUE);
        mSeekbarLum.setProgress(MID_VALUE);

    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        switch (seekBar.getId()){
            case R.id.seekbar_hue:
                //将0-255的值转换为色调值
                mHue = (progress - MID_VALUE)*1.0F/MID_VALUE*180;
                break;
            case R.id.seekbar_saturation:
                //将0-255值转换为饱和度值
                mSaturation = progress*1.0F/MID_VALUE;
                break;
            case R.id.seekbar_lum:
                //将0-255的值转换为亮度值
                mLum = progress*1.0F/MID_VALUE;
                break;
        }
        mImageView.setImageBitmap(ImageUtils.handleImageEffect(bitmap,
                mHue,mSaturation,mLum));
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

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

Después de ejecutar, arrastre la barra de búsqueda, puede encontrar que hemos cambiado con éxito los atributos de la imagen


Análisis de principios-transformación matricial

Usamos la clase ColorMatrix antes.Como todos sabemos, Matrix significa matriz, así que aquí estamos procesando imágenes manipulando la matriz. Android proporciona una matriz de color como se muestra en la figura para ayudarnos a procesar los efectos de la imagen. Cada punto de la imagen es un componente de la matriz, que se compone de R, G, B, A y 1:

Multiplicamos esta matriz de color por el componente de la matriz de color correspondiente al píxel para obtener una nueva matriz R1G1B1A1. Como se muestra en la figura:

De esta forma, transformamos un píxel en un nuevo píxel a través de la matriz de color (el efecto del ajuste de color).

A la matriz que se muestra en la figura la llamamos matriz de inicialización, porque permanece sin cambios después de multiplicar los píxeles originales.

Echemos un vistazo a esta matriz. Según la matriz original, el 0 en los dos lugares se cambia a 100. El resultado es que el valor de RG original ha cambiado a su valor más 100, que es el RG de cada píxel. todos los valores se incrementan en 100:

De manera similar, podemos echar un vistazo a dicha matriz. Basado en la matriz de inicialización original, un 1 en la matriz G se cambia a 2. Después de traerlo, podemos encontrar que G ha duplicado el valor original. El efecto es El El verde de toda la imagen se duplica.

Podemos encontrar que las cuatro filas de la matriz de color controlan respectivamente los cuatro atributos de RGBA del píxel, y la quinta columna de la matriz de color, la llamamos compensación de color, no cambia directamente el coeficiente de un determinado color, pero Ajuste todo el color según el original.

Necesitamos cambiar un color, no solo podemos cambiar el desplazamiento, sino también cambiar el coeficiente de color.

Utilice la transformación matricial para ajustar los efectos de la imagen

Basándonos en el proyecto original, agregamos una actividad y dejamos que el segundo botón de MainActivity salte a esta actividad.

El primero es el diseño. Hacemos el siguiente diseño. Vamos a agregar 20 EditText para representar la matriz en el GridLayout y usar el botón para aplicar la matriz.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="2"/>

    <GridLayout
        android:id="@+id/group"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="3"
           android:rowCount="4"
        android:columnCount="5"
    </GridLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btn_change"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="改变"/>

        <Button
            android:id="@+id/btn_reset"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="重置"/>

    </LinearLayout>
</LinearLayout>

<

Luego, modificamos el código de Actividad para agregar dinámicamente EditText a GridText para mapear nuestra ColorMatrix. Cambie nuestro ColorMatrix cambiando EditText para cambiar el efecto de la imagen.

public class ColorMatrixActivity extends AppCompatActivity {
    private ImageView mImageView;
    private GridLayout mGroup;
    private Bitmap bitmap;
    private int mEtWidth,mEtHeight;
    private EditText[] mEditTexts = new EditText[20];
    private float[] mColorMatrix = new float[20];   //对应矩阵
    private Button changeButton;
    private Button resetButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_color_matrix);

        bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.test1);
        mImageView = (ImageView) findViewById(R.id.image_view);
        mImageView.setImageBitmap(bitmap);

        mGroup = (GridLayout) findViewById(R.id.group);
        //动态创建EditText,填充GridLayout

        //由于在onCreate中,mGroup还没有创建完成,无法获取宽高
        //所以通过post方法,在控件绘制完毕后,执行Runnable的具体方法
        mGroup.post(new Runnable() {
            @Override
            public void run() {
                mEtWidth = mGroup.getWidth()/5;
                mEtHeight = mGroup.getHeight()/4;
                addEditText();
                initMatrix();
            }
        });

        changeButton = (Button)findViewById(R.id.btn_change);
        changeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                changeButtonEvent();
            }
        });

        resetButton = (Button)findViewById(R.id.btn_reset);
        resetButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                resetButtonEvent();
            }
        });
    }

    private void addEditText(){
        for (int i=0;i&lt;20;i++){
            EditText editText = new EditText(ColorMatrixActivity.this);
            mEditTexts[i] = editText;
            mGroup.addView(editText,mEtWidth,mEtHeight);
        }
    }

    private void initMatrix(){
        for (int i=0;i&lt;20;i++){
            if (i%6 == 0){
                //i为第0、6、12、18位时
                mColorMatrix[i]=1;
                mEditTexts[i].setText(String.valueOf(1));
            }else{
                mColorMatrix[i]=0;
                mEditTexts[i].setText(String.valueOf(0));
            }
        }
    }

    private void getMatrix(){
        for (int i=0;i&lt;20;i++){
            mColorMatrix[i] = Float.valueOf(mEditTexts[i].getText().toString());
        }
    }

    private void setImageMatrix(){
        Bitmap currentBitmap = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        ColorMatrix colorMatrix = new ColorMatrix();
        colorMatrix.set(mColorMatrix);
        Canvas canvas = new Canvas(currentBitmap);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap,0,0,paint);
        mImageView.setImageBitmap(currentBitmap);
    }

    public void changeButtonEvent(){
        getMatrix();
        setImageMatrix();
    }

    public void resetButtonEvent(){
        initMatrix();
        setImageMatrix();
    }
}

Como puede ver, el efecto de la imagen se cambia con éxito, el efecto se muestra en la figura

Después de aprender esto, podemos responder por qué usamos tales parámetros para cambiar el tono, la saturación y el brillo. Tomando el brillo como ejemplo, echemos un vistazo al código fuente del método setScale. Se puede encontrar que ColorMatrix también usa una matriz de colores de este tipo internamente. Al mismo tiempo, el múltiplo de 6 se establece en el valor correspondiente para cambiar el brillo. Muestra que si queremos cambiar el brillo en la matriz de colores, Solo es necesario cambiar el brillo de cada color. El valor se puede aumentar al mismo tiempo.

  /**
    * Set this colormatrix to scale by the specified values.
    */
    public void setScale(float rScale, float gScale, float bScale,float aScale) {
        final float[] a = mArray;
           for (int i = 19; i &gt; 0; --i) {
            a[i] = 0;
        }
        a[0] = rScale;
        a[6] = gScale;
        a[12] = bScale;
        a[18] = aScale;
    }

A través de estos estudios, podemos concluir lo siguiente:

El procesamiento de imágenes, de hecho, consiste en estudiar los efectos de procesamiento de diferentes matrices de colores en las imágenes.

Por ejemplo, podemos obtener el efecto nostálgico común en algunas aplicaciones de procesamiento de imágenes mediante el método de configuración en la siguiente figura.


Procesamiento de imágenes a través de píxeles

Una vez ampliada la imagen, presentará una matriz de puntos y cada punto es en realidad un píxel. A través de la relación de color de RGB, se pueden mostrar diferentes colores.

Los siguientes son algunos ejemplos de procesamiento de píxeles para formar efectos especiales de imagen:

Efecto negativo

Para los tres píxeles de ABC, el algoritmo para encontrar el efecto de película del punto B es el siguiente. De hecho, el color inverso se calcula para cada punto de coordenadas y puede obtener

Br = 255 - Br;
Bg = 255 - Bg;
Bb = 255 - Bb;

Efecto de foto antigua

El algoritmo para encontrar el efecto de la foto antigua en el píxel es el siguiente, donde pixR es el valor R del píxel actual, y así sucesivamente.

newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);

Efecto de alivio

Para los tres puntos ABC, el algoritmo para encontrar el efecto de alivio del punto B es el siguiente.

Br = Cr-Br + 127;
Bg = Cg - Bg + 127;
Bb = Cb - Bb + 127;

A continuación, cambiaremos el efecto de visualización de la imagen modificando los píxeles.

Primero cree una nueva actividad y agregue un método para saltar a ella en el tercer botón de MainActivity.

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

        <ImageView
            android:id="@+id/image_view1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>

        <ImageView
            android:id="@+id/image_view2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1">
        <ImageView
            android:id="@+id/image_view3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>

        <ImageView
            android:id="@+id/image_view4"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"/>
    </LinearLayout>
</LinearLayout>

Agregue el método de efectos especiales correspondiente

Hemos agregado varios métodos nuevos a ImageUtils para realizar diferentes procesamientos

Efecto de color invertido

El código es el siguiente, creamos una nueva matriz de píxeles correspondiente a la imagen y luego obtenemos todos los píxeles a través del método getPixels.
El segundo parámetro de getPixels es el desplazamiento que representa el punto de inicio, y el tercer parámetro es controlar el espaciado de línea al leer la matriz. Generalmente, se usa el ancho. Los dos últimos parámetros representan las coordenadas del punto de píxel leído para el primero tiempo, y el penúltimo El parámetro representa el ancho que leemos del mapa de bits, y el último es la altura leída.
Luego obtenemos los cuatro valores de rgba a través del método alfa rojo, verde, azul de la clase Color para cada píxel, y cambiamos su valor rgb a través del algoritmo, y lo convertimos en una nueva matriz de píxeles a través del método argb de Color. Cabe señalar que al cambiar su valor rgb, debe determinar si excede el límite de 0-255 y, si es alguno, asignarlo a 255 o 0 .

    Bitmap currentBitmap = Bitmap.createBitmap(width,height,
            Bitmap.Config.ARGB_8888);
        int[] oldPx = new int[width*height];    //存储像素点数组
        int[] newPx = new int[width*height];
        bitmap.getPixels(oldPx,0,width,0,0,width,height);
        for (int i=0;i&lt;width*height;i++){
            color = oldPx[i];
            r = Color.red(color);
            g = Color.green(color);
            b = Color.blue(color);
            a = Color.alpha(color);
            //通过算法计算新的rgb值
            r = 255 - r;
            g = 255 - g;
            b = 255 - b;

            if (r &gt; 255) r=255;
            else if (r &lt; 0) r=0;

            if (g &gt; 255) g=255;
            else if (g &lt; 0) g=0;

            if (b &gt; 255) b=255;
            else if (b &lt; 0) b=0;

            newPx[i] = Color.argb(a,r,g,b);
        }
        currentBitmap.setPixels(newPx,0,width,0,0,width,height);
        return currentBitmap;
    }

Efecto de foto antigua

Otros códigos son básicamente los mismos que antes, excepto que el algoritmo se cambia ligeramente y no se puede cambiar sobre la base del rgb original:

    public static Bitmap handleImageOldpicture(Bitmap bitmap){
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int color;
        int r,g,b,a;

        Bitmap currentBitmap = Bitmap.createBitmap(width,height,
                Bitmap.Config.ARGB_8888);
        int[] oldPx = new int[width*height];    //存储像素点数组
        int[] newPx = new int[width*height];
        bitmap.getPixels(oldPx,0,width,0,0,width,height);
        for (int i=0;i&lt;width*height;i++){
            color = oldPx[i];
            r = Color.red(color);
            g = Color.green(color);
            b = Color.blue(color);
            a = Color.alpha(color);

            int r1,g1,b1;
            r1 = (int)(0.393 * r + 0.769 * g + 0.189 * b);
            g1 = (int)(0.349 * r + 0.686 * g + 0.168 * b);
            b1 = (int)(0.272 * r + 0.534 * g + 0.131 * b);

            if (r1 &gt; 255) r1=255;
            else if (r1 &lt; 0) r1=0;

            if (g1 &gt; 255) g1=255;
            else if (g1 &lt; 0) g1=0;

            if (b1 &gt; 255) b1=255;
            else if (b1 &lt; 0) b1=0;

            newPx[i] = Color.argb(a,r1,g1,b1);
        }
        currentBitmap.setPixels(newPx,0,width,0,0,width,height);

        return currentBitmap;
    }

Efecto de alivio

Al igual que en el anterior, lo único que debemos tener en cuenta es que debemos usar el color del píxel anterior, por lo que debemos alternar desde 1 y luego usar el algoritmo correspondiente para obtener la imagen.

    public static Bitmap handleImagePixelsRelief(Bitmap bitmap){
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        int color,colorBefore;
        int r,g,b,a;
        int r1,g1,b1;

        Bitmap currentBitmap = Bitmap.createBitmap(width,height,
                Bitmap.Config.ARGB_8888);

        int[] oldPx = new int[width*height];    //存储像素点数组
        int[] newPx = new int[width*height];
        bitmap.getPixels(oldPx,0,width,0,0,width,height);
        for (int i=1;i&lt;width*height;i++){
            //取出前一个点的颜色
            colorBefore = oldPx[i-1];
            r = Color.red(colorBefore);
            g = Color.green(colorBefore);
            b = Color.blue(colorBefore);
            a = Color.alpha(colorBefore);

            color = oldPx[i];
            r1 = Color.red(color);
            g1 = Color.green(color);
            b1 = Color.blue(color);

            r = (r - r1 + 127);
            g = (g - g1 + 127);
            b = (b - b1 + 127);

            if (r1 &gt; 255) r1=255;

            if (g1 &gt; 255) g1=255;

            if (b1 &gt; 255) b1=255;

            newPx[i] = Color.argb(a,r,g,b);
        }
        currentBitmap.setPixels(newPx,0,width,0,0,width,height);

        return currentBitmap;
    }

Ver efecto

Llamamos al método correspondiente en Activity para ver el efecto.

public class PixelEffectActivity extends AppCompatActivity {
    private ImageView imageView1,imageView2,imageView3,imageView4;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pixel_effect);
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test1);
        imageView1 = (ImageView) findViewById(R.id.image_view1);
        imageView2 = (ImageView) findViewById(R.id.image_view2);
        imageView3 = (ImageView) findViewById(R.id.image_view3);
        imageView4 = (ImageView) findViewById(R.id.image_view4);

        imageView1.setImageBitmap(bitmap);
        imageView2.setImageBitmap(ImageUtils.handleImageNegative(bitmap));
        imageView3.setImageBitmap(ImageUtils.handleImageOldpicture(bitmap));
        imageView4.setImageBitmap(ImageUtils.handleImagePixelsRelief(bitmap));
    }
}

El efecto se muestra en la figura.


Material de referencia
Procesamiento de imágenes de Android: cree Meitu Xiuxiu a partir de él

Este artículo  se ha incluido en el proyecto de código abierto: https://github.com/Android-Alvin/Android-LearningNotes , que contiene rutas de programación de autoaprendizaje en diferentes direcciones, colección de preguntas de entrevistas / sutras faciales y una serie de artículos, etc. Los recursos se actualizan continuamente ...

Supongo que te gusta

Origin blog.csdn.net/weixin_43901866/article/details/114119816
Recomendado
Clasificación