Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Gráficos (https://www.clubdelphi.com/foros/forumdisplay.php?f=8)
-   -   Rotación de bitmap caso especial (https://www.clubdelphi.com/foros/showthread.php?t=54224)

mrnovice 12-03-2008 04:32:06

Rotación de bitmap caso especial
 
Saludos, necesito ayuda help!, soy un caso perdido :D, miren mi situación, es que busqué sobre como rotar una imagen JPEG
  • Pero esta requería ser rotado mediante una bitmap, y seguí buscando
  • Ví en los trucos y efectivamente funcionó, y me ha sido muy útil, sólo que para imágenes muy grandes se tarda(ya que utiliza el método por píxeles), y seguí buscando
  • Encontré una página efg lab creo, donde te muestra optimizaciones por medio del scanline y senos y thetas,y funcionó mejor y dentro de la página venía una optimización de el mismo a 400 X eso hubiera sido perfecto sí,al rotar no cortara la imagen a 90° y 270° ya que este funciona para cuadros(REF1) ya que al voltearlo me rellena con negro y yo solo quería rotarlo jejeXD
  • busqué otra opción pero es un poco más complicada y un poco menos efectiva pero funciona, sólo que tuve problemas al adaptarlo a un JPEG y a eventos on clic(REF2)
Códigos
REF1
Código Delphi [-]
begin
  BitmapRotated.Width  := BitmapOriginal.Width;
  BitmapRotated.Height := BitmapOriginal.Height;
  BitmapRotated.PixelFormat := BitmapOriginal.PixelFormat; //Copy PixelFormat
  {$IFDEF Paletted}
   BitmapRotated.Palette := CopyPalette(BitmapOriginal.Palette); //Copy Palette
  {$ENDIF}
  StartTime := GetTickCount;
  try iRotationAxis := SpinEditI.Value
    except iRotationAxis := 0
  end;
  try jRotationAxis := SpinEditJ.Value
    except  jRotationAxis := 0
  end;
  Theta := -(SpinEditThetaDegrees.Value + SpinEditThetaDegreesHundredths.Value/100) * PI / 180;
  Edit1.text:=' Theta= '+FloatToStr(Theta)+' spe/100= '+ FloatToStr(SpinEditThetaDegreesHundredths.Value/100);
  sinTheta := SIN(Theta);
  cosTheta := COS(Theta);
  ScanlineBytes := Integer(BitmapOriginal.Scanline[1])- Integer(BitmapOriginal.Scanline[0]);
  BW := BitmapOriginal.Width  - 1; //Prevent Repeated Calls to TBitMap.Width
  BH := BitmapOriginal.Height - 1; //Prevent Repeated Calls to TBitMap.Height
  iRot := (2 * iRotationAxis) + 1; //Simplify Calculation within Inner Loop
  jRot := (2 * jRotationAxis) + 1; //Simplify Calculation within Outer Loop
  RowRotated     := BitmapRotated.ScanLine[BH]; //Last BitmapRotated Scanline
  POriginalStart := BitmapOriginal.ScanLine[0]; //First BitmapOriginal Scanline
  for j := BH downto 0 do
    begin
      jPrime := (2 * j) - jRot;
      jPrimeSinTheta := jPrime * sinTheta;
      jPrimeCosTheta := jPrime * cosTheta;
      POriginal := POriginalStart;
      for i := BW downto 0 do
        begin
          iPrime := (2 * i) - iRot;
          iPrimeRotated := ROUND(iPrime * cosTheta - jPrimeSinTheta);
          iOriginal := (iPrimeRotated - 1) div 2 + iRotationAxis;
          if (iOriginal >= 0) and (iOriginal <= BW) then
            begin
              jPrimeRotated := ROUND(iPrime * sinTheta + jPrimeCosTheta);
              jOriginal := (jPrimeRotated - 1) div 2 + jRotationAxis;
              if (jOriginal >= 0) and (jOriginal <= BH) then begin
                  RowOriginal   := Pointer(Integer(POriginal) + (jOriginal * ScanLineBytes));
                  RowRotated[i] := RowOriginal[iOriginal];
                end  else {$IFDEF Paletted}RowRotated[i] := 0;{$ELSE}RowRotated[i] := Black;{$ENDIF}
          end else {$IFDEF Paletted} RowRotated[i] := 0; {$ELSE} RowRotated[i] := Black;{$ENDIF}
      end;{for i}
      Dec(Integer(RowRotated), ScanLineBytes);
    end;{for j}

REF2
Código Delphi [-]
with BitMapOriginal do
    begin
    case pixelformat of
        pfDevice:begin
                  nbits :=  GetDeviceCaps( Canvas.Handle,BITSPIXEL )+1 ;
                  nbytes := nbits div 8;
                  if (nbytes>0)and(nbits mod 8 <> 0) then exit;
                 end;
     pf24bit: nBytes:=3;
        pfCustom:begin
                    GetObject( Handle, SizeOf(DIB), @DIB );
                    nbits := DIB.dsBmih.biSizeImage;
                    nbytes := nbits div 8;
                    if (nbytes>0)and(nbits mod 8 <> 0) then exit;
                 end;
        else exit;
    end;// case
      BitmapRotated.Assign( BitMapOriginal);
  sinTheta := SIN( theta );     cosTheta := COS( theta );
 NewWidth  := ABS( ROUND( Height*sinTheta) ) + ABS( ROUND( Width*cosTheta ) );
 NewHeight := ABS( ROUND( Width*sinTheta ) ) + ABS( ROUND( Height*cosTheta) );
  if ( ABS(theta)*MAX( width,height ) ) > 1 then
    begin
     BitmapRotated.Width  := NewWidth;
     BitmapRotated.Height := NewHeight;
      iRotationAxis := width div 2;
      jRotationAxis := height div 2;
      Rwi := NewWidth - 1;
     Rht := NewHeight - 1;
     Owi := Width - 1;
     Oht := Height - 1;
     TransparentT := pRGBtripleArray( Scanline[ Oht ] )[0];  //**
     FOR j := Rht DOWNTO 0 DO   //1/8/00
       BEGIN //for j
            RowRotatedT := BitmapRotated.Scanline[ j ] ;
           jPrime := 2*j - NewHeight + 1 ;
           FOR i := Rwi DOWNTO 0 DO
            BEGIN //for i
                 iPrime := 2*i - NewWidth   + 1;
               iOriginal := ( ROUND( iPrime*CosTheta - jPrime*sinTheta ) -1 + width ) DIV 2;
               jOriginal := ( ROUND( iPrime*sinTheta + jPrime*cosTheta ) -1 + height) DIV 2 ;
               IF   ( iOriginal >= 0 ) AND ( iOriginal <= Owi ) AND ( jOriginal >= 0 ) AND ( jOriginal <= Oht )THEN
                      begin RowRotatedT[i] := pRGBtripleArray( Scanline[jOriginal] )[iOriginal];end
             ELSE
                    begin RowRotatedT[i] := TransparentT;     end;
              END //for i
       END;//for j
  end;//non-zero rotation
    sicoPhi := sicodiPoint(  POINT( width div 2, height div 2 ),oldaxis );
    with sicoPhi do begin
    NewAxis.x := newWidth div 2 + ROUND( di*(CosTheta*co - SinTheta*si) );
    NewAxis.y := newHeight div 2- ROUND( di*(SinTheta*co + CosTheta*si) );
  end;
    end;{with}
 end;{Rotate Bitmap}

Son fragmentos, nose si alguien se le haga parecido al código, el punto es que si me pudieran ayudar a rotar rectangulos que de hecho las imágenes tamaño carta sin escalar y pués me gustaria saber si se pudiera modificar la ref1 para que este funcione con rectangulos u optimizar la ref2 ó no si hayan escuchado del BitBlt es bueno? me la estoy complicando mucho, también aplicar el procedimiento rotatebitmap en eventos onclick es decir tener un Bitmap:bitmap global, es decir que funcione el rotar como el Microsoft Office Picture Manager

cHackAll 12-03-2008 14:48:13

Revisaste el Truco 455? dudo que tu comentario haya sido de éste porque el mismo no se vale de movimiento de pixeles ni de calculos en punteros ScanLine, sino que mediante la API realiza las rotaciónes.

Solo necesitas convertir el JPEG a BMP y utilizar la función.

Saludos

mrnovice 12-03-2008 17:00:41

Rotación, caso especial
 
Saludos, Muchas gracias, este no lo había visto, parece más sencillo, luego te comentó cómo me fue,voy a probarlo, una pregunta osea las versiones scanline o pixeles son métodos antiguos, ya no se usan, son como la base para lo que tenemos en la actualidad?.

Muchas gracias:)

cHackAll 12-03-2008 17:11:26

Cita:

Empezado por mrnovice (Mensaje 272710)
...una pregunta osea las versiones scanline o pixeles son métodos antiguos, ya no se usan, son como la base para lo que tenemos en la actualidad?.

En ningún momento he sugerido tal cosa, y si fue así me retracto. Acceder a los pixeles es útil para comprender la abstracción de los gráficos... al fin y a cabo un pixel es la mínima unidad utilizada por el mismo monitor. Y usarla no es nada malo en pequeñas medidas.

Usar "ScanLine" es acceder a la matriz de pixeles del gráfico en cuestión, lo que acelera en gran medida la modificación de sus datos pues es la modificación del buffer en memoria que posteriormente será actualizada.

Qué tenemos en la "actualidad"... en realidad si pudiésemos ver el código que realiza la API, estaríamos viendo operaciones en memoria con senos y cosenos. La supuesta ventaja es que una empresa con tantos $$$$, puede pagar a buenos matemáticos que optimicen dicho código (o que por lo menos lo busquen e implementen).

Saludos

mrnovice 12-03-2008 17:30:18

Rotación, caso especial
 
Muchas gracias, saludos.
Muy clara la explicación, mejor no pudo haber quedado.
Ah! :D no lo sugeriste, lo que pasa es que me quedo la duda, porque según investigaba, encontraba nuevos métodos, me imaginaba que cada vez se optimizaba y creo de ahí me vino la confusión.
Si te fijas he tratado de encontrar la solución a rotar pero uff creo que hay diversidad de métodos,sólo que me perdí y no supe si estoy haciendo pasos innecesario.
Ah!!!!!!!, me llamó la atención, qué es una verdad qué, pues en cierta manera las grandes empresas pagan $$$$ para optimizar y esto ayude al avance de la tecnología.
Gracias y arriba club Delphi!!!!:cool:

mrnovice 12-03-2008 18:33:45

Ya lo probe
 
mmm, si funciona, y me gusta el rendimiento, pero me deja un espacio morado y algunos bmp no me los lee......serà que no lee bmps grandes?
voy a tratr de modificar el código para hacerlo funcionar, saludos

cHackAll 12-03-2008 18:57:58

Cita:

Empezado por mrnovice (Mensaje 272742)
...me deja un espacio morado y algunos bmp no me los lee......serà que no lee bmps grandes?

No es morado, es clFuchsia y esta hecho así para realizar las modificaciones en tiempo de ejecución y que el espacio vacío quede como tal en un componente que procese el color de transparencia. Puedes cambiarlo sin problema.

No está probado, pero espero que dicha función procese BMPs de decenas de mega pixeles. Con respecto a los BMPs que no reconoce... si tienes uno pequeño súbelo para corregir el truco (si es que realmente es necesario)

Saludos

mrnovice 13-03-2008 20:17:12

Caso raro
 
Pues estuve investigando aunque muy poco los que no me agarraba era bmps de muchos pixeles aprox su tamaño era 24MB, seguirè invesitgando gracias


La franja horaria es GMT +2. Ahora son las 03:21:23.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi