Android 墨水屏黑白红色阶算法和抖动算法,拿过去直接用

Android 墨水屏黑白红色阶算法和抖动算法, 拿过去直接用, 有问题直接下面问

色阶法
一张图像,我们可以把它划分为几个大的颜色域,图像上的每个像素点根据颜色跟这几个色域的趋近程度,被划分到这些颜色域中去。这种方法比较适用于颜色不多的图像,例如亮色或者三色的形状或者文字图像。以黑白红三色墨水屏为例,处理图像的时候我们希望把它处理成黑白红三色,因此对于一张图像来说,我们可以把图像的所有颜色划分三个大的颜色区域:黑色区域,白色区域,红色区域。

抖动法
对于那些颜色比较多,或者渐变区域比较多的图像,上面的色阶法并不太合适,很多时候图像里面的渐变区域的像素可能跟所有颜色域都很接近,如果用色阶法的画就会让图像丢失很多图像细节。很多摄像头拍摄的图片,通过混合颜色的方法来绘画阴影和过度区域,这些图像中,渐变区域占了大部分
对于人眼来说,很容易把特别小的颜色混淆了,比如两种颜色红和蓝并列,如果把它缩小到足够小的手,在人眼看来会变成一种由红和蓝混合而成的颜色。人眼的缺陷意味着我们可以通过欺骗人眼,利用“混合”的方法来获取更多可以表现的颜色,抖动算法就是采用了这一种现象。

package com.example.cinreadedp.ImageProcess;

import android.graphics.Bitmap;
import android.graphics.Color;


public class EPaperPicture
{
    private static int srcW, srcH; // Width and height of source image
    private static int dstW, dstH; // Width and height of destination image

    private static Bitmap srcBmp; // Bitmap of source image
    private static Bitmap dstBmp; // Bitmap of destination image

    private static int[] curPal; // Current palette


    private static int[][] palettes = new int[][] // Palettes
            {
                    new int[] { Color.BLACK, Color.WHITE                        }, //1黑白
                    new int[] { Color.BLACK, Color.WHITE, Color.RED             }, //2黑白红
                    new int[] { Color.BLACK, Color.WHITE, Color.GRAY            }, //3黑白灰
                    new int[] { Color.BLACK, Color.WHITE, Color.GRAY, Color.RED }, //4黑白灰红
                    new int[] { Color.BLACK, Color.WHITE                        }, //5黑白
                    new int[] { Color.BLACK, Color.WHITE, Color.YELLOW          }, //6黑白黄
                    new int[] {},                                                  //7
                    new int[] { 0xff000000, 0xffffffff, 0xff00ff00, 0xff0000ff, 0xffff0000, 0xffffff00,0xffff8000}, //8RGB 全彩
            };

    // Return the square error of {r, g, b},
    // that means how far them are from standard color stdCol
    //---------------------------------------------------------
    private static double getErr(double r, double g, double b, int stdCol)
    {
        r -= Color.red  (stdCol);
        g -= Color.green(stdCol);
        b -= Color.blue (stdCol);

        return r*r + g*g + b*b;
    }

    // Return the index of current palette color which is
    // nearest to the {r, g, b}
    //---------------------------------------------------------
    private static int getNear(double r, double g, double b)
    {
        int ind = 0;
        double err = getErr(r, g, b, curPal[0]);

        for (int i = 1; i < curPal.length; i++)
        {
            double cur = getErr(r, g, b, curPal[i]);
            if (cur < err) { err = cur; ind = i; }
        }

        return ind;
    }

    // Return the index of current palette color which is
    // nearest to the color clr
    //---------------------------------------------------------
    private static int getNear(int clr)
    {
        return getNear(Color.red(clr), Color.green(clr), Color.blue(clr));
    }

    // Adding of color {r, g, b} into e color array with
    // weight k. Here every r, g or b channel takes one cell
    // in e color array and can have any integer value.
    //---------------------------------------------------------
    private static void addVal(double[] e, int i, double r, double g, double b, double k)
    {
        int index = i * 3;
        e[index    ] = (r * k) / 16 + e[index    ];
        e[index + 1] = (g * k) / 16 + e[index + 1];
        e[index + 2] = (b * k) / 16 + e[index + 2];
    }

    // Returns a color from the current palette
    // which is nearest to source bitmap pixel at (x, y), or
    // returns default color if (x, y) is out of the bitmap
    //---------------------------------------------------------
    private static int nearColor(int x, int y)
    {
        if ((x >= srcW) || (y >= srcH)) return curPal[(x + y) % 2 == 0 ? 1 : 0];
        return curPal[getNear(srcBmp.getPixel(x, y))];
    }

	
   //originalImage 原始图片
   //isLvl 1 色阶算法 0 抖动算法
   //width 输出文件宽度
   //height 输出文件高度
   //index_t  可以选择6种数据格式 palettes 
   
    public static Bitmap createIndexedImage(Bitmap originalImage,boolean isLvl,int width,int height,int index_t)
    {
        //EPaperDisplay epd = EPaperDisplay.getDisplays()[EPaperDisplay.epdInd];
        srcBmp = originalImage;
        dstBmp = Bitmap.createBitmap(width,height, srcBmp.getConfig());

        int palInd = index_t;
       // if (!isRed) palInd = palInd & 0xE;
        curPal = palettes[palInd];

        dstW = dstBmp.getWidth();
        dstH = dstBmp.getHeight();
        
        srcW = srcBmp.getWidth();
        srcH = srcBmp.getHeight();

        int[] srcArr = new int[srcW * srcH];
        int[] dstArr = new int[dstW * dstH];

        int index = 0;
        srcBmp.getPixels(srcArr, 0, srcW, 0, 0, srcW, srcH);

        if (isLvl) //色阶算法
        {
            for (int y = 0; y < dstH; y++)
                for (int x = 0; x < dstW; x++)
                    dstArr[index++] = nearColor(x, y);
        }
        else  //抖动算法
        {

            int aInd = 0;
            int bInd = 1;

            double[][] errArr = new double[2][];

            errArr[0] = new double[3*dstW];
            errArr[1] = new double[3*dstW];

            for (int i = 0; i < dstW; i++)
            {
                errArr[bInd][3*i    ] = 0;
                errArr[bInd][3*i + 1] = 0;
                errArr[bInd][3*i + 2] = 0;
            }

            for (int j = 0; j < dstH; j++)
            {
                if (j >= srcH)
                {
                    for (int i = 0; i < dstW; i++, index++)
                        dstArr[index] = curPal[(i + j) % 2 == 0 ? 1 : 0];
                    continue;
                }

                aInd = ((bInd = aInd) + 1) & 1;

                for (int i = 0; i < dstW; i++)
                {
                    errArr[bInd][3*i    ] = 0;
                    errArr[bInd][3*i + 1] = 0;
                    errArr[bInd][3*i + 2] = 0;
                }

                for (int i = 0; i < dstW; i++)
                {
                    if (i >= srcW)
                    {
                        dstArr[index++] = curPal[(i + j) % 2 == 0 ? 1 : 0];
                        continue;
                    }

                    int srcPix = srcArr[j * srcW + i];

                    double r = Color.red  (srcPix) + errArr[aInd][3*i    ];
                    double g = Color.green(srcPix) + errArr[aInd][3*i + 1];
                    double b = Color.blue (srcPix) + errArr[aInd][3*i + 2];

                    int colVal = curPal[getNear(r, g, b)];
                    dstArr[index++] = colVal;

                    r -= Color.red  (colVal);
                    g -= Color.green(colVal);
                    b -= Color.blue (colVal);

                    if (i == 0)
                    {
                        addVal(errArr[bInd], (i    ), r, g, b, 7.0);
                        addVal(errArr[bInd], (i + 1), r, g, b, 2.0);
                        addVal(errArr[aInd], (i + 1), r, g, b, 7.0);
                    }
                    else if (i == dstW - 1)
                    {
                        addVal(errArr[bInd], (i - 1), r, g, b, 7.0);
                        addVal(errArr[bInd], (i    ), r, g, b, 9.0);
                    }
                    else
                    {
                        addVal(errArr[bInd], (i - 1), r, g, b, 3.0);
                        addVal(errArr[bInd], (i    ), r, g, b, 5.0);
                        addVal(errArr[bInd], (i + 1), r, g, b, 1.0);
                        addVal(errArr[aInd], (i + 1), r, g, b, 7.0);
                    }
                }
            }
        }

        // Put converted pixels into destination image bitmap
        //-----------------------------------------------------
        dstBmp.setPixels(dstArr, 0, dstW, 0, 0, dstW, dstH);
        return dstBmp;
    }
    
    // Returns the index of color in palette
    //-----------------------------------------------------
    public int getVal(int color)
    {
        int r = Color.red(color);
        int b = Color.blue(color);

        if((r == 0xFF) && (b == 0xFF)) return 1;
        if((r == 0x7F) && (b == 0x7F)) return 2;
        if((r == 0xFF) && (b == 0x00)) return 3;

        return 0;
    }
    // Returns the index of color in palette just for 5.65f e-Paper
    //-----------------------------------------------------
    public int getVal_7color(int color)
    {
        int r = Color.red(color);
        int g = Color.green(color);
        int b = Color.blue(color);

        if((r == 0x00) && (g == 0x00) && (b == 0x00)) return 0;
        if((r == 0xFF) && (g == 0xFF) && (b == 0xFF)) return 1;
        if((r == 0x00) && (g == 0xFF) && (b == 0x00)) return 2;
        if((r == 0x00) && (g == 0x00) && (b == 0xFF)) return 3;
        if((r == 0xFF) && (g == 0x00) && (b == 0x00)) return 4;
        if((r == 0xFF) && (g == 0xFF) && (b == 0x00)) return 5;
        if((r == 0xFF) && (g == 0x80) && (b == 0x00)) return 6;
        return 7;
    }


}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值