Jumat, 18 Maret 2022

Algorithma Mengubah warna pada gambar menjadi 64 warna

Demo bisa dilihat disini : code (forkhub.github.io)


Pada tulisan ini Saya akan membahas algorithma untuk mengurangi jumlah warna pada gambar sehingga jumlahnya menjadi 64 warna saja. Kita sering melihat efek ini pada aplikasi pengedit gambar seperti Gimp. 

Dengan mengurangi jumlah warna pada gambar, maka kualitas gambar akan turun, seperti di bawah ini.


Setiap gambar dalam komputer terdiri dari kumpulan piksel, Tiap piksel memiliki 3 komponen warna, yaitu: merah, hijau dan biru. Tiap komponent warna memiliki intensitas mulai dari 0-255. Komputer bisa menampilkan sebanyak (256 x 256 x 256) warna atau sekitar 16 juta warna (16,777,216).

Tidak semua warna ditampilkan secara bersamaan, Saya belum menemukan sebuah gambar komputer yang memiliki warna sebanyak itu. 

Untuk mengubah jumlah warna sebuah gambar menjadi 64 warna saja, kita akan mengubah intensitas dari tiap komponen warna, yang awalnya memiliki 256 level menjadi hanya 4 saja.
 
Intensitas baru yang kita pakai akan terdiri dari 0, 85, 170, dan 255 saja. Angka ini adalah angka bebas. Saya memilih angka tersebut supaya persebarannya rata. Anda bisa mengubah-ubah angkanya untuk mendapatkan berbagai macam effect yang berbeda.

Bila setiap warna hanya memiliki level intensitas sebanyak 4 macam saja, maka jumlah warna yang bisa dihasilkan masimum adalah sebanyak 4 x 4 x 4 atau sama dengan 64 warna.

Dengan penyederhanaan ini maka setiap intensitas dari komponen warna yang ada akan dibulatkan ke intensitas baru yang terdekat. Kita bisa memilih metode pembulatannya: apakah pembulatan ke bawah, ke atas, atau pembulatan ke angka terdekat, atau kita bisa buat selang-seling antara pembulatan ke atas atau kebawah sesuai posisi dari pixelnya. 

Pembulatan selang-seling ini akan memberikan efek dithering, dan ini yang akan Saya pakai disini.

Kode sumbernya adalah sebagai berikut:

window.onload = () => {
    let canvas: HTMLCanvasElement = document.createElement('canvas');

    let ctx: CanvasRenderingContext2D = canvas.getContext('2d');

    let img: HTMLImageElement = document.getElementById('gbr') as HTMLImageElement;

    canvas.style.width = img.naturalWidth + 'px';

    canvas.style.height = img.naturalHeight + 'px';

    canvas.width = img.naturalWidth;

    canvas.height = img.naturalHeight;

    document.body.appendChild(canvas);

    ctx.drawImage(img, 0, 0);

    ubahWarnaGambar(canvas, [0, 85, 170, 255]);
}

function ubahWarnaKomponen(warna: number, level: number[], atas: boolean): number {

    for (let i: number = level.length - 2; i >= 0; i--) {

        if (warna > level[i]) {

            if (atas) {

                return level[i + 1];
            }

            else {

                return level[i];

            }

        }

        else if (warna == level[i]) {

            return warna;

        }

    }

    throw Error('warna tidak ada dalam level');

}

function checkBulatAtas(x: number, y: number): boolean {
    let modx: number = x % 2;
    let mody: number = y % 2;

    return modx == mody;
}

function ubahWarnaGambar(canvas: HTMLCanvasElement, level: number[]): void {

    let ctx: CanvasRenderingContext2D;

    let data: ImageData;

    ctx = canvas.getContext('2d');

    for (let i: number = 0; i < canvas.width; i++) {

        for (let j: number = 0; j < canvas.height; j++) {

            data = ctx.getImageData(i, j, 1, 1);

            data.data[0] = ubahWarnaKomponen(data.data[0], level, checkBulatAtas(i, j));

            data.data[1] = ubahWarnaKomponen(data.data[1], level, checkBulatAtas(i, j));

            data.data[2] = ubahWarnaKomponen(data.data[2], level, checkBulatAtas(i, j));

            ctx.putImageData(data, i, j);
        }

    }

}

Bagian awal dari kode diatas berfungsi untuk menggambar sebuah gambar pada kanvas. Manipulasi gambar akan dilakukan pada kanvas.

Fungsi ubahWarnaGambar() adalah fungsi untuk mengubah warna gambar. Fungsi ini menerima parameter berupa kanvas. Gambar yang akan kita ubah warnanya kita gambar dulu ke dalam kanvas. Kemudian kita akan menggunakan perintah kanvas getImageData() untuk mendapatkan informasi warna dari tiap pikselnya. 

getImageData() akan menghasilkan sebuah object. Dari object ini kita bisa mengakses property data yang berisi berisi informasi tentang intensitas warna merah, hijau, biru, dan juga transparansi dari tiap piksel. 

Selanjutnya kita akan mengubah intensitas dari warna merah, biru dan hijau ini dengan memanggil fungsi ubahWarnaKomponen(). Tiap komponen warna akan dicheck intensitasnya dan dibulatkan ke intensitas yang baru. Pembulatan bisa bersifat ke atas ataupun ke bawah, sesuai dengan nilai yang dibelikan oleh parameter  atas.

Parameter atas didapatkan dari Fungsi checkBulatAtas(). Fungsi ini mengecek apakah kita akan melakukan pembulatan ke atas atau ke bawah. Pembulatan ke atas kita lakukan bila posisi x dan y keduanya sama-sama ganjil atau sama-sama genap. Posisi ini adalah posisi yang letaknya selang-seling seperti posisi kotak pada papan catur.

Hasilnya bisa dilihat pada gambar di atas. Kita bisa meningkatkan kualitas gambar dengan memainkan angka-angka pada intensitas sesuai dengan gambarnya. 

Saat ini nilai intensitas yang baru berlaku pada semua komponen warna, kita bisa menerapkan nilai intensitas yang berbeda untuk setiap komponen warna, dan hasilnya mungkin bisa lebih baik lagi.

Kita akan bahas itu di tulisan selanjutnya. Terima kasih sudah membaca tulisan ini. Bila ada pertanyaan, silahkan langsung tulis di komentar. 
 

Kredit:




    















Tidak ada komentar:

Posting Komentar