Android Floyd-Steinberg-DitheringStucki-dither 抖动处理

Posted 匆忙拥挤repeat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Floyd-Steinberg-DitheringStucki-dither 抖动处理相关的知识,希望对你有一定的参考价值。

文章目录


I. Floyd-Steinberg-Dithering

Github: Native-Floyd-Steinberg-Dithering
该作者对Floyd-Steinberg-Dithering 的处理中,使用的是静态数组,容易栈溢出。
这里,给出两种实现来避免。当然,若一次处理的位图信息过大,也是会堆溢出,OOM的。

I.i. 动态数组实现

cpp 代码如下。

void floydSteinberg1(androidBitmapInfo *info, void *pixels) 
    uint32_t *pixelLine;
    void *p = pixels;
    int w = info->width;
    int h = info->height;
//    uint32_t ary[h][w];
    uint32_t **ary = new uint32_t *[h];
    for (int y = 0; y < h; ++y) 
        ary[y] = new uint32_t[w];
        pixelLine = (uint32_t *) p;
        for (int x = 0; x < w; ++x) 
            //extract the RGB values from the pixel
            ary[y][x] = 0xFF000000 | (pixelLine[x] & 0x00FFFFFF);
        
        p = (char *) p + info->stride;
    

    for (int y = 0; y < h; ++y) 
        pixelLine = (uint32_t *) pixels;
        for (int x = 0; x < w; ++x) 
            uint32_t oldPixel = ary[y][x];
//            uint32_t newPixel = find_closest_palette_color(oldPixel);
            uint32_t newPixel = (int) oldPixel >= 128 ? 0xFFFFFFFF : 0xFF000000;
            pixelLine[x] = newPixel;

            uint32_t err = oldPixel - newPixel;

            if (x + 1 < w)
                ary[y][x + 1] += (int) (err * (7. / 16));
            if (x > 0 && y + 1 < h)
                ary[y + 1][x - 1] += (int) (err * (3. / 16));
            if (y + 1 < h)
                ary[y + 1][x] += (int) (err * (5. / 16));
            if (x + 1 < w && y + 1 < h)
                ary[y + 1][x + 1] += (int) (err * (1. / 16));
        
        pixels = (char *) pixels + info->stride;
    

    for (int y = 0; y < h; ++y) 
        delete ary[y];
    
    delete[] ary;

I.ii. 指针实现

void floydSteinberg2(AndroidBitmapInfo *info, void *pixels) 
    int w = info->width;
    int h = info->height;
    int mid = 128;
    uint32_t min = 0xFF000000;
    uint32_t max = 0xFFFFFFFF;
//    uint32_t minWhite = 0xFFFF0000;
    for (int y = 0; y < h; ++y) 
        for (int x = 0; x < w; ++x) 
            uint32_t pixel = *((uint32_t *) pixels + y * w + x);
//            if (pixel >= minWhite && pixel <= max) //接近白色不处理
//                continue;
//            
            uint32_t err = (int) pixel >= mid ? pixel - max : pixel - min;
            if (x + 1 < w) 
                *((uint32_t *) pixels + y * w + (x + 1)) += (int) (err * (7. / 16));
            
            if (x >= 1 && y + 1 < h) 
                *((uint32_t *) pixels + (y + 1) * w + (x - 1)) += (int) (err * (3. / 16));
            
            if (y + 1 < h) 
                *((uint32_t *) pixels + (y + 1) * w + x) += (int) (err * (5. / 16));
            
            if (x + 1 < w && y + 1 < h) 
                *((uint32_t *) pixels + (y + 1) * w + (x + 1)) += (int) (err * (1. / 16));
            
            pixel = (int) pixel >= mid ? max : min;
            *((uint32_t *) pixels + y * w + x) = pixel;
        
    



II. Stucki

本算法,是从一段c#代码中移植出来的。

void stucki(AndroidBitmapInfo *info, void *pixels) 
    int w = info->width;
    int h = info->height;
    int mid = 128;
    uint32_t max = 0xFF000000;
    uint32_t min = 0xFFFFFFFF;
    for (int y = 0; y < h; ++y) 
        for (int x = 0; x < w; ++x) 
            uint32_t pixel = *((uint32_t *) pixels + y * w + x);
            uint32_t err = (int) pixel >= mid ? pixel - min : pixel - max;
            if (x + 1 < w)
                *((uint32_t *) pixels + y * w + (x + 1)) += (int) (err * (8. / 42));
            if (x + 2 < w)
                *((uint32_t *) pixels + y * w + (x + 2)) += (int) (err * (4. / 42));

            if (x >= 2 && y + 1 < h)
                *((uint32_t *) pixels + (y + 1) * w + (x - 2)) += (int) (err * (2. / 42));
            if (x >= 1 && y + 1 < h)
                *((uint32_t *) pixels + (y + 1) * w + (x - 1)) += (int) (err * (4. / 42));
            if (y + 1 < h)
                *((uint32_t *) pixels + (y + 1) * w + (x)) += (int) (err * (8. / 42));
            if (x + 1 < w && y + 1 < h)
                *((uint32_t *) pixels + (y + 1) * w + (x + 1)) += (int) (err * (4. / 42));
            if (x + 2 < w && y + 1 < h)
                *((uint32_t *) pixels + (y + 1) * w + (x + 2)) += (int) (err * (2. / 42));

            if (x >= 2 && y + 2 < h)
                *((uint32_t *) pixels + (y + 2) * w + (x - 2)) += (int) (err * (1. / 42));
            if (x >= 1 && y + 2 < h)
                *((uint32_t *) pixels + (y + 2) * w + (x - 1)) += (int) (err * (2. / 42));
            if (y + 2 < h)
                *((uint32_t *) pixels + (y + 2) * w + (x)) += (int) (err * (4. / 42));
            if (x + 1 < w && y + 2 < h)
                *((uint32_t *) pixels + (y + 2) * w + (x + 1)) += (int) (err * (2. / 42));
            if (x + 2 < w && y + 2 < h)
                *((uint32_t *) pixels + (y + 2) * w + (x + 2)) += (int) (err * (1. / 42));

            pixel = (int) pixel >= mid ? min : max;
            *((uint32_t *) pixels + y * w + x) = pixel;
        
    


III. 示例

完整示例


以上是关于Android Floyd-Steinberg-DitheringStucki-dither 抖动处理的主要内容,如果未能解决你的问题,请参考以下文章

ps转16位图少了字节

Android逆向系列文章— Android基础逆向

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

android 21 是啥版本

Android逆向-Android基础逆向(2-2)