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 :

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 maksavar 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.
@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
TFrameGrabbervar
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;
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
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
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: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];
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

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).