Obracanie obrazka TIMAGE

0

1.Jak przerzucic w pionie lub poziomie jakis obrazek??
2. jak obrocic jakis obrazek o kąt

0

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

0

mi chodzi o cały obrazek nie o punkt

0

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;
0

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

0

omikron87 - Porównaj czasy wykonywania Twojego kodu z kodem Bełdzia, np na bitmapie 1024x768.

0

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

0

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

0

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.

0

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)

0

Pewnie, że działa, ale trzeba wczytać bitmape, która ma 24bity!!!!!!!!!!!!! albo zmodyfikować kod

chodzi o tą linijkę:

//...
bmp2.PixelFormat:=pf24bit;
//...
0

Witam.

<ort>Odświerze</ort> ten temat.

Czy ma ktoś moze działajacy i sprawny kod na obracanie obrazka w TImage ??

1

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;
0

a jest polecenie, które by było odwrotnością Scanline, takie żeby wpisywało w bitmapę całą linijkę pikseli??

1 użytkowników online, w tym zalogowanych: 0, gości: 1