Pada pertemuan pertama dalam kuliah
grafika komputer ada satu hal penting yang ditanyakan (dijadikan tugas
) yaitu bagaimana caranya
menampilkan titik dengan warna tertentu di layar monitor (dengan mengakses framebuffer)
dan mendapatkan deskripsi tentang warna dari titik dengan koordinat tertentu di
layar. Dalam dunia DOS dulu, hal ini mudah saja (dalam berbagai asumsi) untuk
dilakukan yaitu dengan mengakses memori pada alamat $A0000
dengan data yang dapat diakses tergantung dari mode grafik yang sedang aktif.
Lalu bagaimana melakukan hal ini di delphi (misal menampilkan titik berwarna
tertentu pada form)? hal ini bisa dilakukan melalui Property Pixels
milik objek bertipe TCanvas yang umumnya merupakan milik dari kelas turunan
TWinControl seperti TForm. contoh penggunaan Pixels adalah
sebagai berikut :
{ menampilkan titik berwarna merah di koordinat (10, 10) }
Form1.Canvas.Pixels[10,10] := clRed;
{ atau }
Form1.Canvas.Pixels[10, 10] := RGB(255, 0, 0);
{ mendapatkan pixel dari koordinat tertentu (10, 10) }
var
p : TColor; r, g, b : byte;
{ ... }
p
:= Form1.Canvas.Pixels[10, 10]
{ mendapatkan komponen warna merah, hijau, dan biru }
r
:= GetRValue(p);
g
:= GetGValue(p);
b
:= GetBValue(p);
Cara di atas merupakan cara termudah untuk mengakses pixel pada suatu
koordinat di layar (maksudnya form, hehehe) namun bukan merupakan cara
tercepat. Masih ada cara lain yang lebih cepat. saya pertama kali merasakan
lambatnya Pixels ketika mengikuti kuliah Grafika Komputer (3 tahun yang lalu)
dan membuat tugas menggunakan Delphi (tadinya pakai turbo pascal 7) tapi
akhirnya mengikuti anggota kelompok lain yang lebih akrab dengan Delphi
daripada turbo pascal.
Cara lainnya untuk mengakses pixel adalah dengan menggunakan properti
scanline dari kelas TBitmap. Kenapa menggunakan TBitmap? awalnya sih karena
untuk menampilkan gambar di Delphi saya menggunakan komponen TImage dan di
dalam TImage ada properti Picture yang kemudian properti Bitmap yang merupakan
kelas bertipe TBitmap (
garing hehehe..) yang akhirnya sampai sekarang
saya gunakan untuk keperluan pengolahan citra ataupun menggambar (grafika).
Untuk menggunakan scanline dengan
nyaman ada beberapa hal yang perlu
untuk dideklarasi terlebih dahulu.
type
{ asumsi PixelFormat yang digunakan adalah 24 bit (pf24bit) }
TWarnaRGB = packed record
b, g, r : Byte;
end;
{ packed; jadi 1 record ukurannya persis 3 byte,
klo nggak pake packed nanti ukurannya
di-align ke 4 byte jadinya 4x3 = 12 byte; }
TArrRGB = array[0..65535] of TWarnaRGB;
PArrRGB = ^TArrRGB; { tipe properti scanline adalah Pointer }
Tipe data bentukan di atas akan digunakan dalam potongan kode berikut:
procedure PutPixel(b:TBitmap; x, y:integer; rr, gg, bb : byte);
var p : PArrRGB;
begin
p := b.Scanline[y];{ 10 adalah baris/ordinat(y) pada Bitmap }
with p[x] do begin
r := rr;
g := gg;
b := bb;
end;
end;
procedure GetPixel(b:TBitmap; x, y:integer; var r, g, b : Byte);
var p : PArrRGB;
begin
p := b.Scanline[y];
r := p[x].r;
g := p[x].g;
b := p[x].b;
end;
Kode di atas mengasumsikan properti
PixelFormat milik
TBitmap
bernilai pf24bit yang artinya Bitmap menyimpan informasi gambar sebanyak 3
byte
per titik (r, g, dan b). Jika bitmap yang dimiliki tidak dalam format 24 bit
maka ubah saja ke dalam format 24 bit dengan kode berikut (sedikit maksa
var b : TBitmap;
{ .. }
b.PixelFormat := pf24bit;
1. · mas…say amo tanya. klo pengen mendapatkan
matriknya rgb dari gambar bagaimana caranya?truz ditampilkan di stringgrid.coz
aq masih bingung. trimakasih ya mas.
i@tris: gambarnya di iterate aja
var
i,j:integer;
p : PArrRGB;
b:TBitmap; {
gambarnya }
sg : TStringgrid; {
gridnya }
{ .. }
for j := 0 to b.Height-1 do begin
{ iterate row }
p := b.Scanline[j];
for i := 0 to b.Width-1 do begin
{ iterate column }
sg.Cells[i, j] :=
IntToStr(p[i].r)+','+IntToStr(p[i].g)+','+IntToStr(p[i].b);
end;
end;
2. untuk mengakses gambar dari Web
Cam, saya pakai komponen DSPack dari progdigy.com di situ ada komponen
TFrameGrabber
ada method untuk GetBitmap (cara halus)
cara kasarnya(tanpa pakai FrameGrabber tapi nyuri dari canvas TVideoWindow):
BitBlt(VideoWindow1.Canvas.Handle, 0, 0, VideoWindow1.Width,
VideoWindow1.Height, MyBitmap.Canvas.Handle, 0, 0, pmSrcCopy);//klo ga salah lo ya.. coba cek di help Win32 SDK
3. · mas, aku
nyoba pakek looping sampai Height-1 dan Width-1. tp kok nge-run nya lama?
gmn cara agar dapet RGB tp gak selama itu?
trimakasih banyak atas bantuannya ya mas i
tris:lamanya mungkin karena
dimasukkan ke dbgrid mas, perlu konversi dari bilangan bulat ke string
karakter, trus update data di stringgrid. memang harus ke string grid ya mas?
hehe.. kalo memang harus, mendingan sementara ditampung dulu ke stringlist of
stringlist
var i,j:integer;
p :
PArrRGB;
b:TBitmap;//gambarnya
s1, s2 :
TStrings;
sg :
TStringgrid;//gridnya
s1 := TStringlist.Create;
s2 := TStringlist.Create;
for j := 0 to b.Height-1 do begin //iterate row
p := b.Scanline[j];
s2.Clear;
for i := 0 to b.Width-1 do begin //iterate column
s2.Add(IntToStr(p[i].r)+','+IntToStr(p[i].g)+','+IntToStr(p[i].b));//simpan
di stringlist
end;
s1.Add(s2.CommaText);
end;
//sekarang dikopi ke string grid
sg.RowCount := s1.Count+sg.FixedRows;
for j := 0 to s1.Count-1 do //iterate row
sg.Rows[sg.FixedRows+j].CommaText := s1[j];
4. Peb, mo nanya nih! gw pernah baca
di buku teknik pengolahan citra digital menggunakan delphi, tentang binarisasi
karya Balza Achmad. begini bunyinya:
var
i,j,Ambang,gray:integer;
PC,PH:Pbytearray;
begin
Ambang:=128;
if(form4.Image.Picture.Bitmap.PixelFormat=pf24bit) then
for i:=0 to form4.Image.Picture.Height-1 do
begin
PC:=form4.Image.Picture.Bitmap.ScanLine[i];
PH:=form4.Image.Picture.Bitmap.ScanLine[i];
for j:=0 to form3.Image.Picture.Bitmap.Width-1 do
begin
gray:=round((PC[3*j]+PC[3*j+1]+PC[3*j+2])/3);
if (gray
5. bedanya pbytearray dengan PArrRGB
gw itu :
klo pbytearray itu menunjuk record yang ukurannya 1 byte. sedangkan pArrRGB gw
itu menunjuk record yang ukurannya 3 byte. sebenarnya sama, hanya saja.. gw
nggak harus mengalikan dengan 3 dan menambah 1 dan 2 untuk mengakses nilai
green, dan red. soalnya udah dibungkus sama record TWarnaRGB.
dengan asumsi urutan penyimpanan
elemen pixel di windows adalah bgr bukan rgb maksud pernyataan di atas spt
ini:
PC[3*j] itu untuk mengakses elemen blue yang ke-j
PC[3*j+1] untuk mengakses elemen green yang ke-j
PC[3*j+2] untuk mengakses elemen red yang ke-j
dikalikan 3 karena tiap pixel membutuhkan tempat penyimpanan sebesar 3 x 1
byte per elemen (b 1 byte, g 1 byte, r 1 byte). jadi ketika mengalikan j (iterator
kolom) dengan 3, nilai yang ditunjuk oleh PByteArray adalah nilai blue, nilai
green dan red adalah 1-2 byte setelah posisi blue tsb.
pointer yang gw gunakan adalah pointer of array of record (bgr) bukan
pointer of array of byte. jadi, dari struktur record itu udah ada offset dari
pointer untuk merujuk ke elemen yang gw maksud (r, g, b) dan pengaksesan nilai
masing-masing elemen sudah dibuat oleh compiler jadi tidak perlu lagi
susah-susah melakukan operasi aritmatika terhadap alamat pointer (pointer arithmetic)
6. untuk melakukan image flipping
hanya diperlukan pertukaran pixel. misal untuk flip horizontal maka pixel pada
koordinat [i, j] ditukar dengan pixel pada koordinat [i, image.height-j] untuk
i bernilai dari 0 sampai image.width-1 dan j dari 0 sampai image.height div
2. untuk vertical flip yang ditukar adalah pixel yang berada di atas dengan di
bawah garis tengah horizontal.
//vertical flip
var
i, j : integer;
b : TBitmap;
p, p2 : PArrRGB;
w : TWarnaRGB;
begin
for j := 0 to (b.Height div 2)-1 do begin
p := b.scanline[j];
p2 := b.scanline[b.Height-1-j];
for i := 0 to b.Width-1 do begin
//tukar
w := p[i];
p[i] := p2[i];
p2[i] := w;
end;
end;
end;
untuk horizontal flip yang ditukar adalah pixel kiri dengan kanan garis tengah
vertikal.
//horizontal flip
var
i, j : integer;
b : TBitmap;
p : PArrRGB;
w : TWarnaRGB;
begin
for j := 0 to b.Height-1 do begin
p := b.scanline[j];
for i := 0 to (b.Width div 2)-1 do begin
//tukar
w := p[i];
p[i] := p[b.Width-1-i];
p2[b.Width-1-i] := w;
end;
end;
end;
untuk melakukan putaran lebih enak menggunakan dua buah image. pemetaan
pixel dapat dilakukan secara maju (
forward mapping) atau terbalik (
backward
mapping). pemetaan maju memetakan posisi tiap pixel di citra sumber ke
posisi baru di citra tujuan dengan nilai pixel di posisi baru adalah nilai
pixel di citra asal. fungsi yang digunakan adalah fungsi transformasi geometrik
rotasi biasa. sedangkan untuk pemetaan mundur tiap posisi pixel di citra tujuan
dipetakan menggunakan fungsi invers rotasi sehingga menghasilkan posisi titik
yang bersesuaian pada citra asal. nilai pixel yang digunakan tetap dari citra
asal.
7. Mas saya lagi coba mbuat program
deteksi warna RGB pake TImage
Kenapa ya, warna yang terdeteksi Cuma bagian kiri dari image.???
Misalnya image yang diambil bentuknya kotak berwarna merah bagian kiri 25% dan
75% berwarna biru disebelah kanannya.
Walaupun image yang dimbil 75% berwarna biru tapi nilai R selalu lebih tinggi,
kenapa ya……???
Listing programnya gini
var
x,y: integer;
R, G, B, jmlpixel : longint;
begin
R := 0;
G := 0;
B := 0;
jmlpixel := 0;
for x := 0 to image1.Height-1 do
for y := 0 to image1.Width-1 do
begin
R := R + GetRValue(Image1.Picture.Bitmap.Canvas.Pixels[x,y]);
G := G + GetGValue(Image1.Picture.Bitmap.Canvas.Pixels[x,y]);
B := B + GetBValue(Image1.Picture.Bitmap.Canvas.Pixels[x,y]);
jmlpixel := jmlpixel + 1;
end;
R := round(R/jmlpixel);
G := round(G/jmlpixel);
B := round(B/jmlpixel);
Edit1.Text := intToStr(R);
Edit2.Text := intToStr(G);
Edit3.Text := intToStr(B);
End;
Da saran ga…..
Maksih ya……….
kebalik tuh
for x := 0 to image1.Height-1 do
for y := 0 to image1.Width-1 do
semestinya
for y := 0 to image1.Height-1 do
for x := 0 to image1.Width-1 do
8.
beda bmp dan jpg
1. BMP dan JPEG hanya berbeda format penyimpanan aja. BMP juga ada yang
dimampatkan, biasanya sih pakai Run-Length Encoding walaupun pada umumnya BMP
adalah format tidak termampat yang artinya informasi pixel di simpan
mentah-mentah. kalau JPEG itu format yang disusun sebagai standar, sesuai kepanjangan
JPEG (Joint Photographic Expert Group). dikompresi dengan huffman coding, tapi
sebelumnya ditransformasi ke domain spasial dengan transformasi kosinus diskret
(DCT)(agak mirip dengan MP3 untuk suara). FYI, JPEG2000 menggunakan DWT
(Discrete Wavelet Transform) untuk mengurangi kelemahan diskretisasi DCT.
2. untuk bitmap dengan format pixel 8 bit. tiap pixelnya adalah index ke
tabel lookup(palet warna) yang berisi informasi RGB. jadi jumlah warna yang
mungkin untuk bitmap 8 bit adalah 256 warna. kualitasnya kemungkinan besar
tidak sama seperti 24 bit karena ada kuantisasi dari 2 milyar warna ke 256
warna.
9. Mo nanya lagi ni (sory nanya mulu,
maklum ‘no skill’ hehe..)
Gmn yah cara ngubah warna citra (kita batasin format .bmp 24 bit aj) dari
grayscale (hitam..abu..putih) menjadi spektrum color/pelangi
(me..ji..ku..hi..bi..ni..u).
Maksudnya gini, misal: yang tadinya warna kehitam2an jadi sekitar warna
merah, trus yang warna keabu2an mgkn jd sekitar warna kuning/hijau, yg warna
keputihan menjadi sekitar warna ungu .
Dengan kata lain, gw pengen ngubah pallete color gambarnya.
hmm.. mungkin bisa dicoba dari model warna HSV/HSI (Hue-Saturation-Value)
komponen Hue itu klo tidak salah pola warna pelangi.
jadi pertama bikin gradasi mejikuhibinu dari model HSV yang dikonversi ke
RGB (H bervariasi 0-255, S=255, V=127, CMIIW). lalu disampling dari gradasi
mejikuhibinu tsb diasosiasikan dengan tingkat 0-255 dari greyscale.
type
warnargb=
packed
record
b, g, r : byte;
end;
var
paletrgb:array [0..255] of warnargb;
h,s,v:byte;
begin
s := 255;
v := 127;
for
h := 0
to
255
do begin
//konversi hsv
ke rgb
paletrgb[h] := hsv_to_rgb(h, s, v);//saya lupa definisinya
end;
end;
//apply paletrgb ke palet bitmap
greyscale
10. kok citra pengubinan saya yang
saya buat dengan perintah
‘somebitmap’.Canvas.Draw(x,y,’somebitmap’);
kalo digabungkan (blending) dengan image yang lain kok selalu muncul noise
y??
untuk fungsi gabungnya kira-kira seperti ini :
procedure Tform1.Gabung(im1,im2 : TImage);
var
i, j,posisi : integer;
PC, PC2, PH : PByteArray;
w1,w2 : real;
begin
w1 :=trackbar1.Position;
w1 := w1/10;
w2 := 1-w1;
im2.Picture.Bitmap.Height := im1.Picture.Bitmap.Height;
im2.Picture.Bitmap.Width := im1.Picture.Bitmap.Width;
progressbar5.Min := 0;
progressbar5.Max := (im1.Picture.Bitmap.Width-1)*(im1.Picture.Bitmap.Height-1);
if (im1.Picture.Bitmap.PixelFormat = pf8bit) then
begin
for i := 0 to im1.Picture.Bitmap.Height-1 do
begin
PC := im1.Picture.Bitmap.ScanLine[i];
PC2 := im2.Picture.Bitmap.ScanLine[i];
PH := image1.Picture.Bitmap.ScanLine[i];
for j := 0 to im1.Picture.Bitmap.Width-1 do
PH[j] := Round(PC[j]*w1+PC2[j]*w2);
posisi := i*j;
progressbar5.Position := posisi;
end;
end;
if (im1.Picture.Bitmap.PixelFormat = pf24bit) then
begin
for i := 0 to im1.Picture.Bitmap.Height-1 do
begin
PC := im1.Picture.Bitmap.ScanLine[i];
PC2 := im2.Picture.Bitmap.ScanLine[i];
PH := image1.Picture.Bitmap.ScanLine[i];
for j := 0 to im1.Picture.Bitmap.Width-1 do
begin
PH[3*j] := Round(PC[3*j]*w1+PC2[3*j]*w2);
PH[3*j+1] := Round(PC[3*j+1]*w1+PC2[3*j+1]*w2);
PH[3*j+2] := Round(PC[3*j+2]*w1+PC2[3*j+2]*w2);
posisi := i*j;
progressbar5.Position := posisi;
end;
end;
end;
end;
11. Mau nanya nih, saya lagi buat
image encoding dengan metode lsb. Pertama saya scanline image untuk dapetin
RGBnya, kemudian nilai rgb saya ubah menjadi biner. dari biner tadi saya buat
rgb baru yang jadi warna hitam per 3 nilai biner.
Saya menggunakan string grid. SG untuk menyimpan nilai rgb perpiksel, SG1 untuk
menyimpan nilai biner per piksel, SG3 untuk memcah nilai biner menjadi
satu-satu. dan SG4 untuk mengambil nilai biner menjadi RGB baru per pixel.
Kemudian dari SG4 di scanline menjadi gambar hitam.
Tapi yang jadi masalah, waktunya terlalu lama dan sering out of memory. ada ide
gimana caranya untuk mempercepat dan meminimalisasi penggunaan memory. Soalnya
saya kurang bisa menggunakan TStrings. berikut contoh program yang saya buat.
procedure TFEncode.GetRgb;
var i,j:integer;
marr : PRGBArray;
begin
LProses.Caption:=’Process : Retrieving Image RGB’;
LProses.Refresh;
Eimage.Picture.Bitmap.PixelFormat:= pf24bit;
sg.RowCount:=Eimage.Picture.Bitmap.Height;
sg.ColCount:=Eimage.Picture.Bitmap.Width;
for j := 0 to Eimage.Picture.Bitmap.Height-1 do begin //iterate row
marr := Eimage.Picture.Bitmap.Scanline[j];
for i := 0 to Eimage.Picture.Bitmap.Width-1 do begin //iterate column
sg.Cells[i,j]:=IntToStr(marr[i].Red)+’,'+IntToStr(marr[i].Green)+’,'+IntToStr(marr[i].Blue);
end;
end;
end;
procedure TFEncode.GetBiner;
var
i,j : integer;
hasil : TStringList;
t1,t2,t3,KATA, data:STRING;
begin
LProses.Caption:=’Process : Convert Image RGB to Binary’;
LProses.Refresh;
sg1.ColCount:=sg.ColCount;
sg1.RowCount:=sg.RowCount;
for i:=0 to sg.RowCount-1 do begin
for j:=0 to sg.ColCount-1 do begin
kata:=sg.Cells[j,i];
hasil:=split(kata,’,');
t1:=IntTobin(StrToInt(hasil[0]));
t2:=IntTobin(StrToInt(hasil[1]));
t3:=IntTobin(StrToInt(hasil[2]));
data:=t1+’,'+t2+’,'+t3;
sg1.Cells[j,i]:=data;
end;
end;
end;
procedure TFEncode.GetLsb;
var
i,j,x,y,z : integer;
hasil : TStringList;
KATA,temp:STRING;
begin
LProses.Caption:=’Process : Encode The Binary’;
LProses.Refresh;
sg3.ColCount:=sg1.ColCount*24;
sg3.RowCount:=sg1.RowCount;
for i:=0 to sg1.RowCount-1 do begin
y:=0;
for j:=0 to sg1.ColCount-1 do begin
kata:=sg1.Cells[j,i];
hasil:=split(kata,’,');
for z:=0 to 2 do begin
temp:=hasil[z];
for x:=0 to 7 do begin
sg3.Cells[y,i]:=copy(temp,x+1,1);
y:=y+1;
end;
end;
end;
end;
end;
procedure TFEncode.NewRgb;
var
i,j,y : integer;
t1,t2,t3,data:STRING;
begin
LProses.Caption:=’Process : Make The Black Image RGB’;
LProses.Refresh;
sg4.ColCount:=sg3.ColCount div 3;
sg4.RowCount:=sg3.RowCount;
for i:=0 to sg3.RowCount-1 do begin
y:=0;
j:=0;
repeat
t1:=sg3.Cells[j,i];
t2:=sg3.Cells[j+1,i];
t3:=sg3.Cells[j+2,i];
data:=t1+’,'+t2+’,'+t3;
sg4.Cells[y,i]:=data;
j:=j+3;
y:=y+1;
until j>sg3.ColCount;
end;
end;
procedure TFEncode.GetBImage;
var mbmp : TBitmap;
size, mw, mh, x, y : integer;
marr : PRGBArray;
KATA:STRING;
hasil : TStringList;
begin
LProses.Caption:=’Process : Making Black Image’;
LProses.Refresh;
mbmp := TBitmap.Create;
mbmp.PixelFormat := pf24bit;
mbmp.Width := sg4.ColCount;
mbmp.Height := sg4.RowCount;
mw := mbmp.Width; mh := mbmp.Height;
marr := mbmp.ScanLine[0];
size := Integer(mbmp.ScanLine[1]) – Integer(mbmp.ScanLine[0]);
for y := 0 to (mh – 1) do begin
for x := 0 to (mw – 1) do begin
//the heart of our mechanism – this loop goes through pixels of each row
//and we can modify contents of each pixel’s color data
kata:=sg4.Cells[x,y];
hasil:=split(kata,’,');
marr^[x].Red :=strtoint(hasil[0]);
marr^[x].Green := strtoint(hasil[1]);
marr^[x].Blue := strtoint(hasil[2]);
end;
Integer(marr) := Integer(marr) + size;
end;
EHasil.Picture.Graphic:=mbmp;
HW.Caption:=inttostr(mbmp.Width);
HH.Caption:=inttostr(mbmp.Height);
mbmp.Free;
end;
Tapi yang jadi masalah, waktunya terlalu lama dan sering out of memory. ada
ide gimana caranya untuk mempercepat dan meminimalisasi penggunaan memory.
hehehe.. pake stringgrid sih..
terlalu banyak konversi string to integer dan sebaliknya yang jadi lama
langsung
nyemplung ke scanline aja dan beroperasi pada tipe data
numerik (integer)..
12. mas bagaimana cara mendapatkan nilai pixels biner atau
monochrom
cara sederhananya (walau kurang efisien secara memori)
dengan mengonversi bitmap dari format pixel pf1bit atau pf4bit menjadi pf24bit.
untuk bitmap yang format aslinya adalah biner maka nilai pixel RGB yang ada
hanya (0, 0 ,0) dan (255, 255, 255). untuk memeriksa cukup menggunakan properti
r (warna merah).
13. Mas pebbie..saya minta tolong ni…
saya buat fungsi untuk baca image bmp grayscale kemudian saya mau ubah nilai
matriks pixel bmp ke dalam baris(array) dengan metode zig-zag misalnya.
matriks 4 x 4
23 10 3 1
9 7 2 0
8 1 0 0
4 1 0 0
jadi kalo di ubah ke dalam baris [23 10 9 8 7 3 1 2 1 4 1 0 0 0 0 0]
saya udah coba buat fungsi untuk matrik ke baris dan posting di delphi-id
juga tapi
dengan metode berurutan yaitu baris1 lanjut baris selanjutnya.
gimana mas peb ya kalo dengan metode zig-zag tersebut buat ubah nilai pixel
ke baris dengan metode zig-zag……mohon bantuannya mas peb..
unit UnitBacaImage;
interface
uses Unit1,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs, ExtCtrls, ComCtrls, Buttons, StdCtrls, ExtDlgs;
Function BacaImage(x :Timage): Pmatrik;
implementation
Function BacaImage(x :Timage): Pmatrik;
var
h,w,i,j : integer;
grey : PMatrik;
PH

byteArray;
begin
h := x.Picture.Height;
w := x.Picture.Width;
setlength(grey,h,w);
for i:= 0 to h – 1 do
begin
PH := x.Picture.Bitmap.ScanLine[i];
for j:= 0 to w – 1 do
begin
grey[i,j]:= PH[j];
End;
End;
BacaImage := Grey;
end;
end.
unit UnitMatrikJadiBaris;
interface
uses Unit1,Windows,Messages,SysUtils,Variants,Classes,Graphics,Controls,Forms,
Dialogs,ExtCtrls,ComCtrls,Buttons,StdCtrls,ExtDlgs;
function matrikjadibaris(B : PMatrik) : PArray;
implementation
function matrikjadibaris(B : PMatrik) : PArray;
var
i, j, baris, kolom : integer;
indeks : integer;
deret : PArray;
begin
setlength(deret, length(B)*length(B[0]));
baris := length(B);
kolom := length(B[0]);
indeks := 0;
for i := 0 to baris – 1 do
begin
for j := 0 to kolom – 1 do
begin
deret[indeks] := B[i][j];
inc(indeks);
end;
end;
matrikjadibaris := deret;
end;
end.
procedure TForm1.BitBtnWatermarkingClick(Sender: TObject);
var
hasilpixel : PArray;
k : integer;
ww : textfile;
begin
data1 := BacaImage(formcitra.Image1);
barispixel := matrikjadibaris(data1);
end;
end.
mungkin ini saja mas pebbie…mohon maaf, terima kasih….
14 . saya ubah gambar RGB ke
grayscale / keabuan pakai metode YIQ, sehinggan natinya yang diambil adalah
komponen Y saja untuk gambar keabuannya menurut teori yang ada, formulanya
dapet dari matlab.
kalo di buku pengolahan citra pake delphi (pak ahmad balzah ada) cuman
harus pake metode YIQ ini
Tapi kenapa hasil konversinya itu bukan seperti gambar grayscale melainkan
seperti gambar klise Photo( gambar negatif album photo)
Saya deklarasikan tipe
type
PMatrik = array of array of real;
DWarna = record
biru : PMatrik;
hijau : PMatrik;
merah : PMatrik;
end;
YIQ = record
Y : PMatrik;
I : PMatrik;
Q : PMatrik;
end;
public
pixelRGB : Dwarna;
keabuan : YIQ;
pixelkeabuan,pixelkeabuan2 : PMatrik;
Fungsinya seperti ini :
function RGBtoYIQ(X : DWarna): YIQ;
var
y : YIQ;
h,w,j,i : integer;
begin
h := length(x.biru);
w := length(x.biru[0]);
setlength(y.Y,h,w);
setlength(y.I,h,w);
setlength(y.Q,h,w);
for i:= 0 to h – 1 do
for j:= 0 to w – 1 do
begin
y.Y[i,j] := 0.299*(x.merah[i,j]) + 0.857*(x.hijau[i,j]) + 0.114*(x.Biru[i,j]);
y.I[i,j] := 0.596*(x.merah[i,j]) – 0.274*(x.hijau[i,j]) – 0.322*(x.Biru[i,j]);
y.Q[i,j] := 0.211*(x.merah[i,j]) – 0.523*(x.hijau[i,j]) + 0.312*(x.Biru[i,j]);
end;
RGBToYIQ := y;
End;
Kemudian saya load gambar RGB
procedure TFormUtama.Button6Click(Sender: TObject);
var
fcrgb : string ;
begin
if (openpicturedialog2.Execute) then
begin
if (form2 = nil ) then
application.CreateForm(TForm2, form2);
form2.Image1.Picture.LoadFromFile(openpicturedialog2.FileName);
form2.ClientHeight := form2.Image1.Picture.Height;
form2.ClientWidth := form2.Image1.Picture.Width;
form2.ClientHeight := form2.Image1.Picture.Height;
case
(form2.Image1.Picture.Bitmap.PixelFormat) of
pf1bit : fcrgb := ‘biner’;
pf8bit : fcrgb := ‘keabuan’;
pf24bit : fcrgb := ‘true color’;
end;
end;
end;
kemudian lakukan konversi RGB ke grayscale
procedure TFormUtama.Button7Click(Sender: TObject);
begin
pixelRGB := BacaImageRGB(form2.Image1);
keabuan := RGBtoYIQ(pixelRGB);
pixelkeabuan2 := keabuan.Y;
edit4.Text := inttostr(length(keabuan.I));
if (form3 = nil) then
application.CreateForm(TForm3, form3);
form3.Left := form3.Left + 120;
form3.Top := form3.Top – 25;
end;
di form3nya untuk menampilkan citra grayscalenya listingnya seperti ini :
unit Unit3;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;
type
logpal = record
lpal : Tlogpalette;
entry : array [0..255] of TPaletteEntry;
end;
type
TForm3 = class(TForm)
Image1: TImage;
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
paletkeabuan : logpal;
implementation
uses
unitutama;
{$R *.dfm}
Procedure GambarIDwt(y:PMatrik;x:Timage);
var
PH : PbyteArray;
bitmap2 :Tbitmap;
i,j,p :integer;
begin
x.Height :=length(y);
x.Width :=length(y[0]);
bitmap2 := Tbitmap.Create;
bitmap2.Height :=length(y);
bitmap2.Width :=length(y[0]);
x.Picture.Graphic := bitmap2;
x.Picture.Bitmap.PixelFormat:= pf8bit;
x.Picture.Bitmap.Palette := createpalette(paletkeabuan.lpal);
for i:= 0 to length(y)- 1 do
begin
PH := x.Picture.Bitmap.ScanLine[i];
for j:= 0 to length(y[0])- 1 do
begin
p := round(y[i,j]);
PH[j]:= p;
end;
end;
end;
procedure TForm3.FormCreate(Sender: TObject);
var
i :integer;
begin
paletkeabuan.lpal.palVersion := $300;
paletkeabuan.lpal.palNumEntries := 256;
for i := 0 to 255 do
begin
paletkeabuan.entry[i].peRed := i;
paletkeabuan.entry[i].peGreen := i;
paletkeabuan.entry[i].peBlue := i;
end;
end;
procedure TForm3.FormShow(Sender: TObject);
begin
GambarIDwt(formutama.keabuan.Y,Image1);
end;
end.
15. halo…mas mau nanya lagi nih.
nilai2 piksel kalo aq copy ke canvas image kok ada warna merah itu kenapa ya?
Aq pernah nyoba nilai piksel gambar aku taruh di stringGrid, terus aq copy
lagi ke canvas . Kok ada warna merahnya. makasih sebelunya
kemungkinan nilai
yang anda masukkan bernilai 0-255 sedangkan format pixel (properti PixelFormat)
dari bitmap image (Image.Picture.Bitmap) bukan pf8bit (pf24bit atau pf32bit).
sehingga yang anda atur hanya nilai merahnya saja. *mungkin?*
format pixel 8 bit bukan berarti grayscale (ini
kesalahpahaman yang sering terjadi). format pixel 8 bit itu maksudnya setiap
pixel menyimpan informasi indeks ke tabel Palet yang elemennya berisi informasi
RGB. Bitmap dengan format pixel 8 bit mampu menggunakan model warna RGB tetapi
banyaknya warna (kombinasi RGB) maksimum yang dapat ditampilkan hanya 256 warna
saja.
16. Alow mas pebbie….
Mau nanya lagi neh. Masih bingung..maklum ilmunya masih dangkal.
Misalkan ada program simpan nilai piksel ke stringgrid spt ini
if( image1.Picture.bitmap.PixelFormat= pf8Bit) then
begin
for y := 0 to image1.Picture.Height-1 do
begin
Pimg := image1.Picture.Bitmap.ScanLine[y];
for x := 0 to image1.Picture.Width-1 do
begin
ST.Cells[x,y] := IntToStr(Pimg[x]);
end;
end;
Terus dari nilai2 di cell stringGrid aq simpan di image canvas begini
image2.ClientHeight:=St.colCount;
image2.ClientWidth:=St.RowCount;
for j:=0 to image2.Height-1 do
for i:=0 to image2.Width-1 do
form1.Image2.Canvas.Pixels[i,j]:= strtoint( st.cells[i,j]);
Hasilnya gambarnya ada merah2nya n setelah aq liat nilai pikselnya kok
lain…..Nilainya sekitar 31-an…..
Terus yang bener gimana mas biar nilai dari stringGrid jadi nilai piksel di
image itu?
Thanks bgt ya mas………..
Mohon responnya
kalau gambarnya greyscale waktu menulis kembali ke canvas seperti ini :
tmp := strtoint(st.cells[i,j]);
form1.image2.Canvas.Pixels[i,j] := RGB(tmp, tmp, tmp);
atau PALETTERGB(tmp, tmp, tmp)
17. Mas peb…..
Mau tanya…. Caranya menuliskan ke canvas untuk indeks palet gimana (citra 8
bit) .
Yang mana nilai indeks paletnya dari stringgrid.
Mohon rsponnya ya mas. Dah nyari2 ga bisa juga
kalau untuk citra 8 bit, pakai ini (komponen TBitmap)
procedure putpixel(bmp: TBitmap; x,y:integer; idxwarna:byte);
var
p : PByteArray;
begin
p := bmp.Scanline[ y ];
{
asumsi bmp.PixelFormat = pf8bit; }
p[ x ] := idxwarna;
end;
20.
saya baru belajar ttg
image masih pemula.
1. misalnya ada citra ukuran 30×30 apakah berarti jumlah pixelnya = 900?
2. gimana mencari nilai masing2 R dan G dan B dari sebuah citra RGB, apakah
ada rumusnya?
3. apakah citra RGB itu harus dirubah ke Greyscale dulu untuk mendapatkan
informasi nilai matriksnya?
makasih jawabannya,..
1. betul.
2. citra RGB bisa jadi beberapa macam
- citra 4 atau 8 bit, maksudnya tiap pixel direpresentasikan dengan byte (8
bit) atau satu byte untuk 2 pixel. oleh sebab itu nilai yang mungkin adalah
sebanyak 256 kombinasi warna. 256 kombinasi warna ini menggunakan tabel look-up
yang berisi nilai RGB. jadi belum tentu pixel bernilai 0 itu hitam (R=0, G=0,
B=0) tetapi tergantung pada nilai RGB di tabel palet indeks ke 0 (bisa saja
justru di tabel palet indeks ke 0 kita berikan warna putih (R=255, G=255,
B=255))
- citra 16 bit, jadi tiap pixel direpresentasikan sebagai 2 byte (16) bit.
citra 16 bit sudah mengalokasikan nilai RGB pada tiap pixel/titiknya jadi tidak
memerlukan tabel palet. yang perlu diperhatikan adalah bagaimana nilai RGB
dikodekan ke variabel berukuran 16 bit. kemungkinan yang umum ada 2 yaitu tiap
komponen warna mendapat jatah 5 bit sehingga 1 bit sisanya tidak terpakai. atau
komponen yang ada di tengah (hijau) mendapat jatah lebih yaitu 6 bit (R5G6B5).
- citra 24 bit, tiap pixel direpresentasikan sebagai 3 byte. oleh sebab itu
tiap komponen mendapat jatah 1 byte. kemungkinan warna yang dihasilkan adalah 2
milyar warna.
- citra 32 bit, tiap komponen tetap dialokasikan sebagai 1 byte namun 1 byte
terakhir kalau digunakan maka biasanya berisi informasi untuk operasi
penggabungan citra (
image blending).
untuk mendapat nilai RGB dari citra bisa baca lagi tulisan saya di atas dari
awal menggunakan Pixels dan 3 fungsi Get[R,G,B]Value(dword)
3. tidak harus, tergantung nilai apa yang ingin didapat. kalau memang
informasi yang diinginkan adalah intensitas (luminansi) maka betul, harus
dikonversi atau tiap pixel dimasukkan ke fungsi penghitung nilai intensitas
luminansinya. kalau informasi yang diinginkan adalah spektrum warna (hue) maka
lain lagi.
21. nih saya derim. di delphi-id yang nanya tentang extract warna.
1. apa bedanya akses pixel dengan scanline?
2. apa maksud nilai y dibawah ini:
p := b.Scanline[
y];
akses menggunakan Pixels lebih lambat dan menghasilkan TColor, untuk
mendapatkan nilai komponen R,G,dan B-nya perlu menggunakan fungsi lain (misal
GetRValue(c)) sedangkan kalau menggunakan scanline yang dihasilkan adalah
pointer ke memori yang menyimpan masing-masing pixel dalam representasi yang
bergantung pada nilai PixelFormat. untuk kasus di atas saya asumsikan
PixelFormat-nya bernilai pf24bit. jadinya, tiap pixel disimpan sebagai 3 byte.
maksud y itu adalah baris (nilai yang valid adalah 0 sampai Tinggi Bitmap atau
banyaknya baris dikurangi 1). baris pertama (y=0) adalah baris yang paling
atas.
22 . 1. KK tahu caranya membersihkan
canvas pada image, maksudnya gini,,Sebagai contoh: Dalam 1 aplikasi aq
taruh 1 bh image,1 buah button yg captionnya “persegi” dgn sintaks
image1.canvas.rectangle(100,200,400,600),lalu ada 1 bh button yg captionnya
“New/Baru”,,nah kk tahu sintaks untuk tombol “baru”,,tolong ya k..
2. dalam procedure floodfill,ada parameter Tfillstyle,,untuk mengisi
Tfillstyle contohnya adalah fsborder,selain fsborder nasih ada yg lain ??
Tolong buat daftarnya yah.. soalnya pada turbo pascal fillstyle nya agak beda
dgn pada delphi.
3. kk tahu caranya menggerakkan citra pada image delphi sehingga bisa di
simpan dengan ekstensi GIF..? klo bisa dengan cintohnya ya
oh iya masih ada yg ingin tahu nih..
- Secara Default pixelFormat pada Timage brp bit ?? lalu klo mw pakai 24 bit
bgmana caranya supaya gmbr rectangle atau ellips dsb bisa ditampilkan di image
- Apa image dgn pixelFormat 24bit lebih bagus gambarnya jika dikonversi
menjadi jpg/bmp image
- lalu apa perbedaan terbesar dari pixel yg berformat 8bit,24bit,32bit
dll,tolong ya kk
- Tolong juga kasi daftar style untuk Brushstyle dan Penstyle pada canvas
image
- Yg terakhir untuk procedure ARC, aq rada-rada bingung nih,soalnya
parameternya sdkt berbeda dgn di pascal, Procedure ARC(x1:integer;y1:integer;x2:integer;y2:integer;x3:integer;y3:integer;x4:integer;y4:integer);
x1,y1-x2,y2 aq ngerti tapi x3,y3,x4,y4 aq bingung jadi misalnya diaplikasikan
dengan SpinEdit yg memiliki nilai integer..aq harus kasih maxvaluenya berapa
untuk x3,y3,x4,y4..jelaskan dong x3,y3 dan x4,y4 supaya misalnya arc yg ingin
dibentuk bisa jadi sesuai dgn yg diinginkan…
makasih banyak ya atas jawabannya……….
1. clear canvas : pakai saja FillRect seperti berikut
with image1.canvas do begin
Brush.Style := bsSolid;
Brush.Color := clWhite; { warna latar belakang, misal putih }
Pen.Style := psClear;
FillRect(Image1.ClientRect);
Pen.Style := psSolid;
end;
2. dari definisi floodFill sbb
procedure FloodFill(X, Y: Integer; Col: TColor; FillStyle: TFillStyle);
parameter FillStyle ada 2 yaitu:
– fsBorder : ini mirip boundary fill, arsir akan dilakukan sampai ketemu pixel
berwarna Col (sebagai batas)
– fsSurface : arsir dilakukan selama pixel yang ditemui warnanya sama dengan
Col
3. maaf, nggak bisa bantu (silakan cari sendiri di google)

4. default pixelformat saya tidak tahu, sepertinya kalau tidak pf32bit maka
akan mengikuti setting display monitor.
5. untuk menggambar (rectangle, elips) tidak terpengaruh oleh properti
PixelFormat. gunakan saja prosedur gambar dari TCanvas
6. bit depth (pixel format) akan mempengaruhi sebanyak apa kombinasi warna
yang bisa disimpan dalam image. misal untuk pf8bit maka kombinasi warna yang
mungkin hanya sebanyak 28 atau 256 warna saja. sedangkan 24 bit dapat menyimpan
kombinasi warna merah sebanyak 256 warna, hijau, dan biru sehingga total
sebanyak ~ 2 milyar warna (oleh sebab itulah disebut true color), 16 bit dapat
menyimpan kombinasi 65 ribu warna. khusus untuk 32 bit, banyaknya warna yang bisa
disimpan sama dengan 24 bit, sedangkan 8 bit sisanya biasanya tidak digunakan
atau digunakan untuk menyimpan informasi transparansi (alpha channel) untuk
melakukan penggabungan (blending) citra.
7. daftar style bisa dilihat sendiri di Help delphi
8. prosedur Arc (garis lengkung)
parameter x1y1 dan x2y2 sama seperti menggambar elips
dengan tambahan x3y3 dan x4y4, parameter ini adalah parameter untuk
membatasi garis elips yang digambar. misal dari titik tengah elips (misal x0y0)
ditarik garis ke x3y3 dan x4y4 maka garis elips yang digambar hanyalah dari
titik perpotongan garis elips dengan garis x0y0-x3y3 dan perpotongan garis
elips dengan garis x0y0-x4y4 melawan arah gerakan jarum jam.
23. mas,sorry neh mo nanya tentang
J2ME,ada ga’method untuk mengambil pixel di J2ME?
thanks
pakai method getRGB dari class Image
int[] imageData = new int[inputImage.getWidth() *
inputImage.getHeight()];
inputImage.getRGB(imageData, 0, inputImage.getWidth(), 0, 0,
inputImage.getWidth(), inputImage.getHeight());
nanti untuk mengakses tiap pixelnya (r, g, b) di posisi (X, Y) dari image
data pakai formula
int pixel = imageData[Y * inputImage.getWidth() + X];
int r = 0xFF & (pixel >> 16);
int g = 0xFF & (pixel >> 8);
int b = 0xFF & pixel;
24. k pebie kenapa nama komponen di
delphi awalannya selalu huruf ‘T’ ? sepert Tcanvas,Tbutton,Tform dlll
Apa artinya atau singkatannya..
Makasih ya
itu cuma kesepakatan penulisan aja kok.. untuk menyatakan bahwa itu adalah
tipe baru (baik itu sebagai kelas atau record) sehingga kalau memberi nama
variabel tinggal membuang ‘T’nya saja (contoh praktisnya).