圖片特效

一開始以為寫程式製作圖片特效是很複雜困難的事情,最近接觸了一點點之後,發現其實沒有想像中的那麼難,並不是什麼天才科學家才能做的事呢!本章將示範在 Android 上實作修圖特效,並以簡單的負片效果作為範例。

參考資料:
[Android Developer]Color

首先介紹一下負片效果,簡單的說就是將色彩反轉,以補色的模式呈現,例如:黑色(0,0,0)的補色是白色(255,255,255),黃色(255,255,0)的補色是藍色(0,0,255)。在 Android 上處理圖片必須先將圖轉為 Bitmap 格式,才能進行處理。

Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);

轉為 Bitmap 格式之後,透過 getPixels 方法將其轉為整數陣列,此時圖上的每一個像素都已經分別轉為一個個整數並且存放在整數陣列裡面,而在 Java 裡面一個 int 是 32 位元,所以此時你看到的整數,這 32 位元包含:透明度(alpha)、紅(r)、藍(g)、綠(b)。拆解開來之後就可以進行補色的運算囉!

public Bitmap invertColor(Bitmap bitmap) {

    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int[] pixels = new int[width*height];
    // Convert bitmap to int array
    bitmap.getPixels(pixels, 0, width, 0, 0, width, height);

    for(int i = 0; i < pixels.length; i++){
        // Extracted from a color int
 
        int a = (pixels[i]) >> 24 & 0xff;
        int r = (pixels[i]) >> 16 & 0xff;
        int g = (pixels[i]) >> 8 & 0xff;
        int b = (pixels[i]) & 0xff;

        // Invert color
        r = 255-r;
        g = 255-g;
        b = 255-b;
        // Encode colot ints
        pixels[i] = (a & 0xff) << 24 | (r & 0xff) << 16 | (g & 0xff) << 8 | (b & 0xff);
    }


    bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    // Convert int array to bitmap
    bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
    return bitmap;
}

加粗紅體字的部份是拆解的關鍵,我們先用一個範例來說明一下完整的過程。

黃色(255,255,255,0)轉為二進制表示法:

ARGB
11111111111111111111111100000000

為了單獨將 R 取出,必須先使用位移運算子(Shift operator)將其右移16個單位,然後左邊補上原來最左邊的位元值:



AR
11111111111111111111111111111111

接著再使用位元運算子(Bitwise operator)裡面的 AND,將上方的值與 0xff 做 AND 的邏輯處理,其中 0xff 是十六進制表示法,其代表整數 255,轉為二進制表示法就如下方所示:

0xff00000000000000000000000011111111
&
color11111111111111111111111111111111

複習一下計算機概論的 AND 邏輯閘運算:

  X     Y     F  
0 0 0
0 1 0
1 0 0
1 1 1

依據上方表格,我們會得到如下結果:




R
00000000000000000000000011111111

這樣一來就可以單獨處理這個 Pixel 裡面 R 的部份囉!這就是上面範例程式碼加粗紅體字的部份,其運作的原理。

若覺得上述方法太複雜的朋友,沒有關係,Android 真的很佛心得提供了很多 API 讓開發者使用,我們可以直接使用 Color 類別提供的方法來達到相同的目標,如下所示。

for(int i = 0; i < pixels.length; i++){
    int a = Color.alpha(pixels[i]);
    int r = Color.red(pixels[i]);
    int g = Color.green(pixels[i]);
    int b = Color.blue(pixels[i]);
    pixels[i] = Color.argb(a, 255-r, 255-g, 255-b);
}

有沒有覺得輕鬆許多了呢?像我這種懶人最喜歡套用別人寫好的 API 了呵呵!接下來看看效果如何吧!上方是原圖,下方是經過處理之後的模樣。

可以很明顯的看到原來的黑色變成白色,原來偏黃色的部份變成藍色,代表已經成功囉!有沒有覺得很有趣阿!而且一點也不困難喔!

留言

  1. The New Game Of Baccarat
    The new game of baccarat is called the new Game of Baccarat, which is a very exciting, exciting and popular game 바카라 사이트 유니 88 that is on our website.

    回覆刪除

張貼留言

這個網誌中的熱門文章

程式語言常用之符號與詞彙 - 中英文對照

什麼是 Bootloader?

Repo 實用指令