Menampilkan Citra Bitmap dari Sebuah Array
Ditulis oleh A.D Setiawan di/pada April 24, 2008
Menindaklanjuti post sebelumnya tentang citra bitmap di C# programming, ada beberapa pertanyaan yang muncul. Bagaimana kita menampiulkan sebuah citra bitmap grayscale dengan nilai-nilai intensitas warna yang sudah diketahui. Nilai intensitas warna ini tersimpan di sebuah array katakanlah bertipe data byte sebab nilainya berkisar diantara 0 – 255. OK … idenya adalah buat sebuah objek Bitmap kosong dengan dimensi sesuai dengan citra yang diinginkan. Objek ini nantinya akan diisi data citra yang berupa nilai intensitas keabuan (0-255) yang berasal dari sebuah array. Teknik ini akan memanfaatkan method locBits dan unlockBits (lihat posting ini). Dalam percobaan kali ini, citra yang digunakan adalah citra lena512.bmp dengan dimensi 512 x 512 piksel. Percobaan yang akan dilakukan adalah :
- membaca citra lena512.bmp dengan menginstansiasi kelas Bitmap
- melakukan lockBits pada objek hasil (1) dengan pixelFormat.Format8bppIndexed
- mengcopy bitmapData hasil lockBits pada (2) ke sebuah array
- Instansiasi objek Bitmap dengan dimensi sama seperti dimensi citra lena512.bmp dengan pixelFormat.Format8bppIndexed
- melakukan lockBits pada objek (4)
- mengcopy bitmapData objek Bitmap pada (4) ke sebuah array
- mengcopy array pada (3) ke array pada (6)
- Mengcopy array pada (6) ke bitmapData hasil lockBits pada (4)
- melakukan unlockBits objek (4)
- melakukan unlockBits objeck (1)
- menampilkan citra pada objek Bitmap (4)
Diagram dari langkah-langkah percobaan tersebut dapat dilihat pada link ini ( soalnya kalau lihat daftar di atas sepertinya jadi agak membingungkan
). Listing program untuk melakukan percobaan di atas saya tuliskan di bawah ini:
// read image from file
Bitmap lena = new Bitmap("lena512.bmp");
BitmapData dataLena =
lena.LockBits(new Rectangle(0, 0, 512, 512),
ImageLockMode.ReadOnly,
PixelFormat.Format8bppIndexed);
IntPtr adressLena = dataLena.Scan0;
int ukuranArrLena = 512 * 512;
byte[] colorArrLena = new byte[ukuranArrLena];
System.Runtime.InteropServices.Marshal.Copy(
adressLena,
colorArrLena, 0, ukuranArrLena);
// Create blank bitmap
Bitmap lena8bpp =
new Bitmap(512, 512,
PixelFormat.Format8bppIndexed);
BitmapData dataLena8bpp =
lena8bpp.LockBits(new Rectangle(0, 0, 512, 512),
ImageLockMode.ReadWrite,
PixelFormat.Format8bppIndexed);
IntPtr adressLena8bpp = dataLena8bpp.Scan0;
int ukuranArrLena8bpp = 512 * 512;
byte[] colorArrLena8bpp = new byte[ukuranArrLena8bpp];
// manipulasi
for (int i = 0; i < ukuranArrLena; i++) {
colorArrLena8bpp[i] = colorArrLena[i];
}
System.Runtime.InteropServices.Marshal.Copy(
colorArrLena, 0,
adressLena8bpp,
ukuranArrLena8bpp);
// unlockbits
lena8bpp.UnlockBits(dataLena8bpp);
lena.UnlockBits(dataLena);
mPictureBox.Image = lena8bpp;
Hasilnya sungguh membuat saya terhenyak. Hasilnya dapat dilihat pada gambar di bawah ini sebelah kanan. Harapan kita adalah gambar sebelah kiri. Pikiran saya adalah: bukankah saya sudah mendifinisikan formatpixel = Format8bppIndexed, mengapa yang muncul malah gambar berwarna? Usut punya usut ternyata definisi dari Format8bppindexed sesuai MSDN adalah
Specifies that the format is 8 bits per pixel, indexed. The color table therefore has 256 colors in it.
Ha .. ternyata format ini bukan dikhususkan untuk citra keabuan (grayscale), justru format ini adalah citra berwarna dengan indeks warnanya sebanyak 256 buah. OK jadi apa yang harus kita lakukan. Hmmm ada ide, bagaimana kalau kita gunakan Format24bppRgb yang merupakan format citra berwarna dengan 3 komponen RED, GREEN, dan BLUE masing-masing diindeks sebasar 8 bit. Wah bagaimana ini, bukankah kita ingin menampilkan citra keabuan. Mudah saja …. kita set masing-masing komponen dengan nilai yang sama. Diagramnya dapat dilihat pada link ini. Hebatnya lagi Format24bppRgb didukung oleh .NET CF (compact framework) , sehingga bisa digunakan untuk memrogram aplikasi citra di PDA. Sebaliknya Format8bppIndexed tidak didukung oleh .NET CF.

Listing programnya adalah sebagai berikut:
// read image from file
Bitmap lena = new Bitmap("lena512.bmp");
BitmapData dataLena =
lena.LockBits(new Rectangle(0,0,512,512),
ImageLockMode.ReadOnly,
PixelFormat.Format8bppIndexed);
IntPtr adressLena = dataLena.Scan0;
int ukuranArrLena = 512 * 512;
byte[] colorArrLena = new byte[ukuranArrLena];
System.Runtime.InteropServices.Marshal.Copy(
adressLena, colorArrLena,
0, ukuranArrLena);
// create blank bitmap
Bitmap citra =
new Bitmap(512, 512,
PixelFormat.Format24bppRgb);
BitmapData dataCitra =
citra.LockBits(new Rectangle(0,0,512,512),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
IntPtr adressLena24bpp = dataCitra.Scan0;
int ukuranArrCitra = 512 * 512*3;
byte[] colorArrLena24bpp = new byte[ukuranArrCitra];
System.Runtime.InteropServices.Marshal.Copy(
adressLena24bpp,
colorArrLena24bpp, 0, ukuranArrCitra);
// manipulasi
int j = 0;
for (int i=0; i < ukuranArrCitra; i+=3) {
colorArrLena24bpp[i] = colorArrLena[j];
colorArrLena24bpp[i + 1] = colorArrLena[j];
colorArrLena24bpp[i + 2] = colorArrLena[j];
j++;
}
System.Runtime.InteropServices.Marshal.Copy(
colorArrLena24bpp, 0,
adressLena24bpp, ukuranArrCitra);
citra.UnlockBits(dataCitra);
lena.UnlockBits(dataLena);
mPictureBox.Image = citra;
Nah hasil dari teknik persis seperti yang kita harapkan, yaitu seperti pada gambar di atas sebelah kiri … HORE … OK semoga pengalaman saya ini bermanfaat buat teman-teman. Salam
