1.Jak przerzucic w pionie lub poziomie jakis obrazek??
2. jak obrocic jakis obrazek o kąt
najprostrzy sposob na obrot obrazka o 180 stopni jest:
np mama czerwny punkt(3,4). to w naszym drugim obrazie bedzie to (4,3). robimy to z kadym punktem. Czyli tylko 2 petelki, i koniec. nie chce mi sie myslec, to ci nie bede pisal teraz kodu:P
mi chodzi o cały obrazek nie o punkt
bite
procedure OdbijWPoziomie(Bitmapa : TImage);
var
bmp2: TBitmap;
x, y: integer;
linia: PByteArray;
begin
bmp2:=TBitmap.Create;
bmp2.PixelFormat:=pf24bit;
bmp2.Width:=Bitmapa.Picture.Bitmap.Width;
bmp2.Height:=Bitmapa.Picture.Bitmap.Height;
for y:=0 to bmp2.Height-1 do
begin
linia:=Bitmapa.Picture.Bitmap.ScanLine[y];
for x:=0 to bmp2.Width-1 do
bmp2.Canvas.Pixels[(bmp2.Width-1)-x,y]:=RGB(linia[x*3+2], linia[x*3+1], linia[x*3]);
end;
Bitmapa.Picture.Bitmap.Assign(bmp2);
bmp2.Free;
end;
procedure OdbijWPionie(Bitmapa : TImage);
var bmp2: TBitmap;
x, y: integer;
linia: PByteArray;
begin
bmp2:=TBitmap.Create;
bmp2.PixelFormat:=pf24bit;
bmp2.Width:=Bitmapa.Picture.Bitmap.Width;
bmp2.Height:=Bitmapa.Picture.Bitmap.Height;
for y:=0 to bmp2.Height-1 do
begin
linia:=Bitmapa.Picture.Bitmap.ScanLine[y];
for x:=0 to bmp2.Width-1 do
bmp2.Canvas.Pixels[x,(bmp2.height-1)-y]:=RGB(linia[x*3+2], linia[x*3+1], linia[x*3]);
end;
Bitmapa.Picture.Bitmap.Assign(bmp2);
bmp2.Free;
end;
popracowałem troszkę nad tymi procedurami i powstały mi funkcje :P
function TForm1.OdbijWPionie(Bitmapa: TBitmap): TBitmap;
var
x, y: integer;
begin
Result:=TBitmap.Create;
Result.PixelFormat:=pf24bit;
Result.Width:=Bitmapa.Width;
Result.Height:=Bitmapa.Height;
for y:=0 to Result.Height-1 do
begin
for x:=0 to Result.Width-1 do
Result.Canvas.Pixels[(Result.Width-1)-x,y] := Bitmapa.Canvas.Pixels[x,y];
end;
end;
function TForm1.OdbijWPoziomie(Bitmapa: TBitmap): TBitmap;
var
x, y: integer;
begin
Result:=TBitmap.Create;
Result.PixelFormat:=pf24bit;
Result.Width:=Bitmapa.Width;
Result.Height:=Bitmapa.Height;
for y:=0 to Result.Height-1 do
begin
for x:=0 to Result.Width-1 do
Result.Canvas.Pixels[x,(Result.Height-1)-y] := Bitmapa.Canvas.Pixels[x,y];
end;
end;
a po co jest to ScanLine?
A swoją droga to ciekawe jest to obracanie o kąt ;)
omikron87 - Porównaj czasy wykonywania Twojego kodu z kodem Bełdzia, np na bitmapie 1024x768.
Kurcze! Rzeczywiście! 3 i pół raza szybciej się wykonuje, no ale jak to działa!?!? Dlaczego tak jest? Podoba mi się ten problem, a szczególnie z obracaniem obrazka o kąt. Jeśli będę wiedział dlaczego tak jest to to wykorzystam. Plis! Wytłumaczcie!
Pozdrawiam!!!
PS. testowałem na obrazku 1600x1200
moim sposobem było około 8 sekund
a sposobem Bełdzia niecałe dwie i pół
Dobra poradziłem sobie z tym ScanLine (niezawodne F1, sorki, że nie od razu).
Powiem krótko funkcje trygonometryczne siem kłaniają :P
X? =x * cos(a) - y * sin(a);
Y? =x * sin(a) + y * cos(a);
Gdzie A to kąt w radianach.
Ps. Polecam zrobienie tablicy TCOS i TSIN o wymiarach 0..359 w których zapiszemy wartości odpowiednio sin i cos dla każdego kąta .
Tak nawiasem mówiąc nie trzeba wykonywać tych obliczeń dla każdego punktu bitmapy!!! Tzn. wystarczy wyliczyć obrót dla najdłuższej krawędzi :) czyli jeśli mamy 1024x768 to wykonujemy powyższy wzór tylko 1024 razy :) Wyobraźcie sobie wykonać obliczenia dla całości !! 1024*768 = 786432 różnice widać na oko :P
2,5 sekundy to i tak dużo. Chodzi o to że podczas operacji na Pixels[x,y] za każdym razem gdy zmieniana jest wartość piksela odświeżana jest cała bitmapa, co zajmuje trochę czasu. Dla obrazka 1600x1200 odświeżanie wykonywane jest 1920000 razy, zupełnie niepotrzebie. Przy ScanLine robione jest to "tylko" 1200 razy - czytamy i zapisujemy linia po linii. Natomiast w większości przypadków wystarczyło by tylko raz - po zakończeniu operacji na pikselach. Niestety to już wymaga stosowania własnego sposobu na dostanie się do pikseli bitmapy.
Ten kod jest nie patrzylem o co chodzi w tym kodzie, ale to co otrzymalem po jego uzyciu malo mialo wspolnego z odbij w pionie. Czy wam dziala ten kod?? (kod Bełdzia)
Pewnie, że działa, ale trzeba wczytać bitmape, która ma 24bity!!!!!!!!!!!!! albo zmodyfikować kod
chodzi o tą linijkę:
//...
bmp2.PixelFormat:=pf24bit;
//...
Witam.
<ort>Odświerze</ort> ten temat.
Czy ma ktoś moze działajacy i sprawny kod na obracanie obrazka w TImage ??
Obrót obrazka o dowolny kąt
Macie tu przykładowy programik obracajacy image o kąt
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, GR32_Image;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Image1: TImage;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
angle:double;
implementation
Const PixelMax = 32768;
Type
pPixelArray = ^TPixelArray;
TPixelArray = Array[0..PixelMax-1] Of TRGBTriple;
{$R *.dfm}
Procedure RotateBitmap_ads(
SourceBitmap : TBitmap;
out DestBitmap : TBitmap;
Center : TPoint;
Angle : Double);
Var
cosRadians : Double;
inX : Integer;
inXOriginal : Integer;
inXPrime : Integer;
inXPrimeRotated : Integer;
inY : Integer;
inYOriginal : Integer;
inYPrime : Integer;
inYPrimeRotated : Integer;
OriginalRow : pPixelArray;
Radians : Double;
RotatedRow : pPixelArray;
sinRadians : Double;
begin
DestBitmap.Width := SourceBitmap.Width;
DestBitmap.Height := SourceBitmap.Height;
DestBitmap.PixelFormat := pf24bit;
Radians := -(Angle) * PI / 180;
sinRadians := Sin(Radians);
cosRadians := Cos(Radians);
For inX := DestBitmap.Height-1 Downto 0 Do
Begin
RotatedRow := DestBitmap.Scanline[inX];
inXPrime := 2*(inX - Center.y) + 1;
For inY := DestBitmap.Width-1 Downto 0 Do
Begin
inYPrime := 2*(inY - Center.x) + 1;
inYPrimeRotated := Round(inYPrime * CosRadians - inXPrime * sinRadians);
inXPrimeRotated := Round(inYPrime * sinRadians + inXPrime * cosRadians);
inYOriginal := (inYPrimeRotated - 1) Div 2 + Center.x;
inXOriginal := (inXPrimeRotated - 1) Div 2 + Center.y;
If
(inYOriginal >= 0) And
(inYOriginal <= SourceBitmap.Width-1) And
(inXOriginal >= 0) And
(inXOriginal <= SourceBitmap.Height-1)
Then
Begin
OriginalRow := SourceBitmap.Scanline[inXOriginal];
RotatedRow[inY] := OriginalRow[inYOriginal]
End
Else
Begin
RotatedRow[inY].rgbtBlue := 255;
RotatedRow[inY].rgbtGreen := 255;
RotatedRow[inY].rgbtRed := 255;
End;
End;
End;
End;
procedure TForm1.Button1Click(Sender: TObject);
Var
Center : TPoint;
Bitmap : TBitmap;
i,j:integer;
begin
Angle:=StrToFloat(Edit1.Text);
Bitmap := TBitmap.Create;
Try
Center.y := (Image1.Height div 2);
Center.x := (Image1.Width div 2);
RotateBitmap_ads(
Image1.Picture.Bitmap, //SourceBitmap : TBitmap;
Bitmap , //DestBitmap : TBitmap;
Center , //Center : TPoint;
Angle );//Angle : Extended): TBitmap;
Image1.Picture.Bitmap.Assign(Bitmap);
Finally
Bitmap.Free;
End;
end;
procedure TForm1.Button2Click(Sender: TObject);
var przekatna:integer;
begin
Image1.Picture.LoadFromFile('aa.bmp');
end;
end.
a to program mojego autorstwa:) - ja robię to na komponentach Image32 - żeby działało na Image to trzeba Image2.Bitmap pozamieniać na Image2.Picture - dacie sobie radę:)
procedure Obroc_o_dowolny_kat(Image, Image2:TImage32; kat:double);
var i,j,kolor:integer;
srodek_x,srodek_y,X,Y,X1,Y1:integer;
roznica_x,roznica_y:integer;
tablica_punktow:array of array of byte;
r1,r2,r3,r4,r5,r6,r7,r8:integer;
g1,g2,g3,g4,g5,g6,g7,g8:integer;
b1,b2,b3,b4,b5,b6,b7,b8:integer;
r_srednie,g_srednie,b_srednie:integer;
kolor_sasiada:TColor;
ilosc:integer;
begin
srodek_x:=Image2.Bitmap.Width div 2;
srodek_y:=Image2.Bitmap.Height div 2;
roznica_x:=(Image.Height-Image2.Bitmap.Height) div 2;
roznica_y:=(Image.Width-Image2.Bitmap.Width) div 2;
Image.Bitmap.Height:=Image.Height;
Image.Bitmap.Width:=Image.Width;
setlength(tablica_punktow,Image.Bitmap.Height,Image.Bitmap.Width);
for j:= 0 to (Image.Bitmap.Width-1) do
for i := 0 to (Image.Bitmap.Height-1) do
tablica_punktow[j,i]:=0;
for j:= 0 to (Image.Bitmap.Width-1) do
for i := 0 to (Image.Bitmap.Height-1) do
Image.Bitmap.Pixels[j,i]:=clWhite;
for j:= 0 to (Image2.Bitmap.Width-1) do
for i := 0 to (Image2.Bitmap.Height-1) do
begin
kolor:=Image2.Bitmap.PixelS[j,i];
X:=j + roznica_x;
Y:=i + roznica_y;
X:=X - srodek_x;
Y:=Y - srodek_y;
X1:=round(X*cos(kat)-Y*sin(kat));
Y1:=round(X*sin(kat)+Y*cos(kat));
X1:=X1 + srodek_x;
Y1:=Y1 + srodek_y;
Image.Bitmap.PixelS[X1,Y1]:=kolor;
if (X1<=Image.Bitmap.Height-1) and (X1>=0) and (Y1>=0) and (y1<=Image.Bitmap.Width-1) then
tablica_punktow[x1,y1]:=1;
end;
for j:= 1 to (Image.Bitmap.Width-2) do
for i := 1 to (Image.Bitmap.Height-2) do
begin
if (tablica_punktow[j,i]=0) then
begin
r1:=0;r2:=0;r3:=0;r4:=0;r5:=0;r6:=0;r7:=0;r8:=0;
g1:=0;g2:=0;g3:=0;g4:=0;g5:=0;g6:=0;g7:=0;g8:=0;
b1:=0;b2:=0;b3:=0;b4:=0;b5:=0;b6:=0;b7:=0;b8:=0;
ilosc:=0;
if tablica_punktow[j-1,i-1]<>0 then
begin
kolor_sasiada:=Image.Bitmap.Pixels[j-1,i-1];
r1:=getRvalue(kolor_sasiada);
g1:=getGvalue(kolor_sasiada);
b1:=getBvalue(kolor_sasiada);
ilosc:=ilosc+1;
end;
if tablica_punktow[j-1,i]<>0 then
begin
kolor_sasiada:=Image.Bitmap.Pixels[j-1,i];
r2:=getRvalue(kolor_sasiada);
g2:=getGvalue(kolor_sasiada);
b2:=getBvalue(kolor_sasiada);
ilosc:=ilosc+1;
end;
if tablica_punktow[j-1,i+1]<>0 then
begin
kolor_sasiada:=Image.Bitmap.Pixels[j-1,i+1];
r3:=getRvalue(kolor_sasiada);
g3:=getGvalue(kolor_sasiada);
b3:=getBvalue(kolor_sasiada);
ilosc:=ilosc+1;
end;
if tablica_punktow[j+1,i-1]<>0 then
begin
kolor_sasiada:=Image.Bitmap.Pixels[j+1,i-1];
r4:=getRvalue(kolor_sasiada);
g4:=getGvalue(kolor_sasiada);
b4:=getBvalue(kolor_sasiada);
ilosc:=ilosc+1;
end;
if tablica_punktow[j+1,i]<>0 then
begin
kolor_sasiada:=Image.Bitmap.Pixels[j+1,i];
r5:=getRvalue(kolor_sasiada);
g5:=getGvalue(kolor_sasiada);
b5:=getBvalue(kolor_sasiada);
ilosc:=ilosc+1;
end;
if tablica_punktow[j+1,i+1]<>0 then
begin
kolor_sasiada:=Image.Bitmap.Pixels[j+1,i+1];
r6:=getRvalue(kolor_sasiada);
g6:=getGvalue(kolor_sasiada);
b6:=getBvalue(kolor_sasiada);
ilosc:=ilosc+1;
end;
if tablica_punktow[j,i-1]<>0 then
begin
kolor_sasiada:=Image.Bitmap.Pixels[j,i-1];
r7:=getRvalue(kolor_sasiada);
g7:=getGvalue(kolor_sasiada);
b7:=getBvalue(kolor_sasiada);
ilosc:=ilosc+1;
end;
if tablica_punktow[j,i+1]<>0 then
begin
kolor_sasiada:=Image.Bitmap.Pixels[j,i+1];
r8:=getRvalue(kolor_sasiada);
g8:=getGvalue(kolor_sasiada);
b8:=getBvalue(kolor_sasiada);
ilosc:=ilosc+1;
end;
if ilosc>=5 then
begin
r_srednie:=(r1+r2+r3+r4+r5+r6+r7+r8) div ilosc;
g_srednie:=(g1+g2+g3+g4+g5+g6+g7+g8) div ilosc;
b_srednie:=(b1+b2+b3+b4+b5+b6+b7+b8) div ilosc;
kolor_sasiada:=RGB(r_srednie,g_srednie,b_srednie);
Image.Bitmap.Pixels[j,i]:=kolor_sasiada
end;
end;
end;
end;
a jest polecenie, które by było odwrotnością Scanline, takie żeby wpisywało w bitmapę całą linijkę pikseli??