Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > API de Windows
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 07-02-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
Entendido escafandrada

Pero al final tienes que crear un stream para pasarle la imagen, es decir solo nos ahorramos el componente TPng pero se "complica" un poco usando las GDI (que tengo que estudiarlas a fondo, gracias por el ejemplo). La funcion "PintaPantalla" con componentes tarda entre 64 y 78 ms en realizar la operacion en casi cualquier PC.
Es las pruebas que he realizado (por cierto que he "cargado" los componentes Indy de la parte del servidor y los e reemplazado por socket, ya sabes bind, linten, accept y thread, luego los sustituyo en el cliente) la eficiencia es similar. Donde mas me preocupa la eficiencia es la copia de zonas de memoria.

Ahora tengo un "RxBuffer: array[0..65535] of ansichar;" en el servidor que lo recoje de "RxLen := recv(nSocket, RxBuffer, 65536, 0);" y veras que tengo un bucle for para copiar el contenido, ahi si creo que estoy fallando en rendimiento. No veo la funcion que permite esa copia de memoria tipo strcopy etc ¿sabes tu cual es?
Bueno en realizad tengo una zona donde recibo del socket que "RxBuffer" y lo copio con "for" al onRecibido y este "ServidorRecibido" incrementa el buffer para generar la imagen. Tambien seria genial saber cual es la funcion que copia, o mejor dicho, incrementa un buffer con el contenido de otro.

Gracias por seguir el tema (curiosa las funciones Lock/UnLock del bitmap, jejeje)

Código Delphi [-]
var
    SCRBuffer: array of ansichar;

procedure TFormPantalla.ServidorRecibido(Sender: TObject);
var
  i, rec, p: integer;
begin
  p := SCRrec; // posicion anterior
  rec := ServidorSCR.RxLen;
  Inc(SCRRec, rec);
  SetLength(SCRbuffer, SCRRec);
  for i := 0 to rec - 1 do
    SCRBuffer[p + i] := ServidorSCR.RxBuffer[i];
  if (GetTickCount() - tOutLoad) > 5000 then
  begin
    Application.MessageBox('TimeOut > 5000 ms', 'Atención', MB_ICONWARNING + MB_OK);
    Imagen.Picture := nil;
    Imagen.Refresh;
    SCRSize := 0;
    SCRRec := 0;
    SetLength(SCRBuffer, 0);
    GaugeLoad.Progress := 0;
    GaugeLoad.Refresh;
    tOutLoad := GetTickCount();
    Exit;
  end;
  GaugeLoad.Progress := Length(SCRBuffer);
  GaugeLoad.Refresh;
  tOutLoad := GetTickCount();
  if SCRrec = SCRSize then
  begin
    PintaPantalla();
    SCRSize := 0;
    SCRRec := 0;
    SetLength(SCRBuffer, 0);
    tFinLoad := GetTickCount();
    STtimeLoad.Caption := IntToStr(tFinLoad - tIniLoad) + ' ms.';
    Pidepantalla();
  end;
end;

procedure TFormPantalla.ProcesaPantalla(recibido: string);
begin
  SCRSize := StrToIntDef(Copy(recibido, 6, Length(recibido) - 6), 0);
  GaugeLoad.MaxValue := SCRSize;
  GaugeLoad.Refresh;
end;

procedure TFormPantalla.PintaPantalla();
var
  LStream: TMemoryStream;
  LPngImage: TPngImage;
begin
  LStream := TMemoryStream.Create;
  LPngImage := TPngImage.Create;
  try
    LStream.Write(SCRBuffer[0], SCRSize);
    LStream.Position := 0;
    LPngImage.Canvas.Lock;
    LPngImage.LoadFromStream(LStream);
    LPngImage.Canvas.Unlock;
    Imagen.Picture.Assign(LPngImage);
    Imagen.Refresh;
  finally
    LStream.Free;
    LPngImage.Free;
  end;
end;

procedure TFormPantalla.PidePantalla;
var
  msg: ansistring;
begin
  tIniLoad := GetTickCount();
  tOutLoad := tIniLoad;
  msg := '[OKSCR]' + #13 + #10;
  ClienteCMD.Envia(AnsiString(msg));
end;
Responder Con Cita
  #2  
Antiguo 07-02-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
Ah escafandra. Un comentario.

La opcion de usar png es que en nivel 1 de compresion (el mas rapido, tienen 9 niveles y 0 es sin comprimir) un "printscreen" solo ocupa unos 300kb para enviar por el socket y una imagen BitMap se va a los 5 Mb, dato muy a tener en cuenta a nivel de rendimiento, aunque supongo que al hacelo en png quedara mas pequeño ¿o no? ¿cuanto ocupara "send(hSocket, Memory^, stat.cbSize, 0);"?

Código Delphi [-]
  GdipCreateBitmapFromHBITMAP(Bitmap, 0, GBitmap);
  GetEncoderCLSID('image/png', Clsid);
  GdipSaveImageToStream(GBitmap, stream, Clsid, nil);

Un saludo.
Responder Con Cita
  #3  
Antiguo 07-02-2012
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por cesarsoftware Ver Mensaje
Pero al final tienes que crear un stream para pasarle la imagen, es decir solo nos ahorramos el componente TPng pero se "complica" un poco usando las GDI
Creas un Stream pero con la API de Windows con lo que ahorras recursos de la VCL aunque su verdadera utilidad sería en un mini servidor que no use VCL y por tanto reduzca su peso consideráblemente.

Cita:
Empezado por cesarsoftware Ver Mensaje
Donde mas me preocupa la eficiencia es la copia de zonas de memoria.

...tengo un bucle for para copiar el contenido, ahi si creo que estoy fallando en rendimiento. No veo la funcion que permite esa copia de memoria tipo strcopy etc ¿sabes tu cual es?
CopyMemory.

Cita:
Empezado por cesarsoftware Ver Mensaje
La opcion de usar png es que en nivel 1 de compresion (el mas rapido, tienen 9 niveles y 0 es sin comprimir) un "printscreen" solo ocupa unos 300kb para enviar por el socket y una imagen BitMap se va a los 5 Mb, dato muy a tener en cuenta a nivel de rendimiento, aunque supongo que al hacelo en png quedara mas pequeño ¿o no? ¿cuanto ocupara "send(hSocket, Memory^, stat.cbSize, 0);"?
Tal como está el código cada pantalla pesa unos 92Kb, pero sabes que png es un formato de compresión sin pérdida de calidad, con lo que pantallas con fotografías o vídeo pasarán bastante mas. La relación de compresión también puede manejarse con GDI+:

Código Delphi [-]
type
TEncoderParameter = packed record
   Guid:           TGUID;
   NumberOfValues: ULONG;
   Type_:          ULONG;
   Value:          Pointer;
end;
PEncoderParameter = ^TEncoderParameter;

TEncoderParameters = packed record
   Count     : UINT;
   Parameter : array[0..0] of TEncoderParameter;
end;
PEncoderParameters = ^TEncoderParameters;


procedure GetEncoderParameters(EP: PEncoderParameters; Quality: PULONG);
const
  EncoderQuality: TGUID = '{1d5be4b5-fa4a-452d-9cdd-5db35105e7eb}';
begin
  // Calidad de imagen y factor de compresión
  // Quality = 100 es la maxima calidad.
  EP.Count:= 1;
  EP.Parameter[0].Guid:= EncoderQuality;
  EP.Parameter[0].Type_:= 4; //Gdiplus::EncoderParameterValueTypeLong;
  EP.Parameter[0].NumberOfValues:= 1;
  EP.Parameter[0].Value:= Quality;
end;
..........

var
  Quality: ULONG;
  EP: TEncoderParameters;
begin
........
GetEncoderParameters(@EP, @Quality);
GdipSaveImageToStream(GBitmap, stream, Clsid, @EP);


Saludos.

Última edición por escafandra fecha: 07-02-2012 a las 14:36:28.
Responder Con Cita
  #4  
Antiguo 07-02-2012
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Otra cosa, ¿Has pensado en utilizar un sistema para enviar por red sólo lo que varía de una imagen a la siguiente, en lugar de pantallas completas?

Mira este enlace: resta de imágenes.


Saludos.

Última edición por escafandra fecha: 07-02-2012 a las 14:50:48.
Responder Con Cita
  #5  
Antiguo 07-02-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
Cita:
Empezado por escafandra Ver Mensaje
Otra cosa, ¿Has pensado en utilizar un sistema para enviar por red sólo lo que varía de una imagen a la siguiente, en lugar de pantallas completas?

Mira este enlace: resta de imágenes.


Saludos.
Co..ño escafandra. Muchas gracias, se ve que te lo curras bien, voy a poner en practica ahora mismo la resta de imagenes.
Que si, que llevaba tiempo pensando en hacerlo pero mas "a pelo" no usando la fuerza bruta e intelegente como la tuya, jejeje.
Supongo que el tema es buscar en las lineas "lo negro" y enviar la parte de la linea que no sea negro indicando X,Y y Len al socket.
Veremos que tal va de rendimiento.

PD: No conocia ese foro, tendre que visitarlo con calma. Ah "CopyMemory" si es que a veces nos pesa la cabeza....

Thanks.
Responder Con Cita
  #6  
Antiguo 07-02-2012
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por cesarsoftware Ver Mensaje
...Supongo que el tema es buscar en las lineas "lo negro" y enviar la parte de la linea que no sea negro indicando X,Y y Len al socket.
No, es mas sencillo que eso. La resta de imágenes te da una gran extensión en negro, al comprimir toda esa imagen, el "negro" no ocupa prácticamente nada, así que comprimes toda esa imagen a png. Luego debes encontrar una máscara de bits de la imagen, para saber que tienes que reconstruir en el PC destino. Simplemente envías dos imágenes de poco peso, la máscara (una imagen de un sólo plano de color) y la resta. En el PC destino basta realizar unas operaciones lógicas binarias con la imagen previa, la máscara y la resta... La API mágica que te va a permitir realizar de golpe esas operaciones, con toda la imagen va a ser BitBlt. Estudia los raster-operation codes.

En el enlace que te dí sobre el tema de resta de imágenes, encontrarás el uso de la API BitBlt con las operaciones lógicas y el uso de máscaras de bit para imágenes. En este otro tema también trabajo con máscaras: Transparencias.


Saludos.
Responder Con Cita
  #7  
Antiguo 07-02-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
Perdona que te lo pregunte directamente escafandra, basicamente por que no entiendo bien el tema de la mascara, o de graficos mejor dicho.
Creo que lo que entiendo es que enviamos una imagen solida, digamos todo en rojo a la que denominamos mascara. Luego enviamos la resta.
En destino comparamos la mascara (todo en rojo) con la resta (todo negro menos los cambios) y obtenemos la diferencia, creo que con OR o XOR.
Ahora aplicamos la diferencia sobre la imagen presentada con un AND. ¿algo asi?

En realidad ¿ como se escribe eso en delphi ?

Te mando una cervecitas por adelantado.
Responder Con Cita
Respuesta



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
liberar memoria Celta Varios 5 12-12-2010 18:07:17
Liberar memoria Sick boy Varios 6 02-07-2005 10:11:29
problema tonto gatsu PHP 2 25-04-2005 21:41:21
Liberar Memoria JoseQ Varios 6 16-07-2004 18:49:21
Liberar Memoria JODELSA Varios 4 13-05-2003 17:39:05


La franja horaria es GMT +2. Ahora son las 17:48:38.


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