Rotar un bitmap x grados (Usando ScanLine)  

Enviado Por: Nacho Urenda
Web : N.A.
Email: nurenda@stonebirds.8m.com
Fecha: 17/08/00

Truco accedido 101 veces

 


  • Primero, añade Math en el uses de tu form
  • Ahora, añade estas lineas tras el uses de tu form:

     const
         MaxPixelCount   =  32768;
    
     type
         pRGBArray  =  ^TRGBArray;
         TRGBArray  =  ARRAY[0..MaxPixelCount-1] OF TRGBTriple;
    



  • Ahora, pon un TImage (Image1) y carga un bitmap en ella
  • Pon un TButton (Button1) y mete este código en su evento OnClick:

     procedure TForm1.Button1Click(Sender: TObject);
    
       procedure FastRotateBitmap(OrigBmp: TBitmap; Angle: real; DestBmp: TBitmap);
       var ang, sinang, cosang, xori, yori, xrot, yrot, dx, dy: extended;
           i, j: integer;
           tmpbmp: TBitmap;
           DestRow: pRGBArray;
       begin
         {  Creamos un bitmap temporal. Esto nos permite usar el mismo bitmap para
            entrada y salida
            Create a temporal bitmap. This allows to use the same bitmap
            as input or output}
         tmpbmp := TBitmap.Create;
    
         try
           {  Asignamos al bitmap temporal las características del original
              Assign the temporal bitmap the same characteristics as the original}
           tmpbmp.Width := OrigBmp.Width;
           tmpbmp.Height := OrigBmp.Height;
           tmpbmp.PixelFormat := OrigBmp.PixelFormat;
    
           { Convertimos grados a radianes.
             Convert degrees to radians. DegToRad() is defined in math.pas}
           ang := DegToRad(Angle);
    
             { Calculamos valores para la traslación
               Calculate translation values}
           dx := (OrigBmp.Width-1) / 2;
           dy := (OrigBmp.Height-1) / 2;
    
             { Calculamos seno y coseno
              SinCos (math.pas) es más rápida que usar sin() y cos() por separado
              Compute sine and cosine
              SinCos (math.pas) is faster than calling sin() and cos() separately}
           SinCos(ang, sinang, cosang);
    
             { Rotación de coordenadas
              Para cada pixel del bitmap de destino, hallamos el correspondiente el el
              bitmap de origen
              Rotate coordinates
              For each pixel in the destination bitmap, we find the corresponding
              pixel in the original bitmap}
    
             { Para cada fila / for each row}
           for i := 0 to tmpbmp.Height -1 do
           begin
               { Asignamos Scanline actual / assign current ScanLine}
             DestRow := tmpbmp.ScanLine[i];
    
               { Para cada columna / for each column}
             for j := 0 to tmpbmp.Width - 1 do
             begin
                 { Trasladamos la coordenada con relación al centro del bitmap
                   Translate coordinate relative to the centre of the bitmap}
               xori := j - dx;
               yori := i - dy;
    
                 { Calculamos las coordenadas rotadas
                   Calculate rotated coordinates}
               xrot := (xori * cosang) - (yori * sinang);
               yrot := (xori * sinang) + (yori * cosang);
    
                 { Deshacemos la traslación
                   Undo translation}
               xrot := xrot + dx;
               yrot := yrot + dy;
    
               if (xrot >= 0) and (xrot < OrigBmp.Width) and
                  (yrot >= 0) and (yrot < OrigBmp.Height) then
               begin
                   { Copiamos el pixel del bitmap de origen al bitmap temporal
                    Copy pixel from origin bitmap to temporal bitmap}
                 DestRow[j] := pRGBArray(OrigBmp.ScanLine[Round(yrot)])[Round(xrot)];
               end else begin
                   { Si las coordenadas están fuera del intervalo, pintamos negro
                     If coordinates are out of range, paint pixel black}
                 DestRow[j].rgbtRed := 0;
                 DestRow[j].rgbtGreen := 0;
                 DestRow[j].rgbtBlue := 0;
               end;
             end;
           end;
    
             { Asignamos el bitmap rotado al bitmap de destino
              Assign the rotated bitmap to the destination bitmap}
           DestBmp.Assign(tmpbmp);
         finally
             { Destruimos bitmap temporal / Destroy temp bitmap}
           tmpbmp.Free;
         end;
       end;
    
     begin
       FastRotateBitmap(Image1.Picture.Bitmap,-10,Image1.Picture.Bitmap);
     end;