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 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
  #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
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
  #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
...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
  #4  
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
  #5  
Antiguo 08-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
Quizás te he liado un poco. Voy a tratar de ser mas claro.

Supón que tenemos un fondo fijo (un campo...) sobre el que se mueve una pelota. Ahora piensa que cada vez que enviemos un fotograma vamos a recordar el previo. A la hora de enviar un nuevo fotograma restamos la nueva imagen y la vieja con el sistema que expliqué en el tema de resta de imágenes. El resultado será que donde previamente estaba la pelota ahora no está, con lo que la resta nos da un círculo con el dibujo del fondo que corresponda en esa posición. La nueva posición de la pelota será representada por la imagen misma de la pelota, y el resto del fondo será negro. Entonces en la resta tenemos:

1- Un fondo negro.
2- Un círculo de imagen de fondo (donde estaba previamente la pelota)
3- Una imagen de la pelota.

Lo sencillo sería trasladar esa imagen resta al PC remoto y pintarla sobre la imagen que tenemos previamente considerando que el fondo negro es transparente (transparencias). Esto parece que funciona muy bien salvo un detalle. Si en la imagen que trasmitimos tenemos zonas negras que no resultan de la resta, se convertirán en zonas trasparentes desvirtuando el resultado final. Para resolver este inconveniente necesitamos diferenciar ambos negros. Tenemos dos opciones o usamos el canal alpha del png (cuarto color) para guardar en el lo que debe ser trasparente o usamos una máscara de un bit (blanco-negro). Esta opción nos permitirá trabajar con formato jpg u otros sin canal alpha. De modo que la máscara lleva la información de lo que será transparente.

Entonces, ¿para que queremos el negro de la imagen resultante de la resta de imágenes?. Pues para que al comprimirla, en el formato que sea, no ocupe lugar.

Espero que con esta explicación entiendas lo que pretendo trasmitir, a veces no me se explicar lo suficientemente bien. Ahora solo te queda estudiar el código para conseguir transparencias con máscaras y la resta de imágenes para que te quede todo un poco mas claro.

Perdona por el rollo y cambiarte los esquemas. Es bastante tarde, mis neuronas no funcionan al 100% y si sigo, te lio mas.


Saludos.
Responder Con Cita
  #6  
Antiguo 08-02-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
Lightbulb

Hola escafandra
Gracias por tus aclaraciones, que se entienen muy bien. Solo me falta entender como componer la imagen con la resta enviada. Quiza me lo expliques mejor mas adelante, pero ahora otro tema que quiza te interese bastante mas.

Ya he aplicado la resta de imagenes.
Despues de muchas pruebas y comprobar que solo funciona si creo como globales los Bitmap que usa CreateSubtractBitmap en vez de crear (no la anterior oldScreen porque esa tiene que ser global si o si) y destruir los objetos cada vez. Con la funcion que presento abajo (muchas gracias por CreateSubstractBitmap) ya envio solo la diferencia. Me queda "completar" la imagen en destino (ahora solo se ve la diferencia/resta, jejeje). Aunque se envie solo la diferencia en bitmap ocupa un monton, asi que sigo enviando en png.
Peeeerooooo.. Al usar tu funcion consecutivamente, a los pocos segundos..."Out of memory resources", si mando la pantalla completa (es decir sin usar la funcion) se puede tirar horas sin "romperse" y sin consumir ram (que es el principio de este hilo, que nos estamos desviando, jejeje).

¿Se te ocurre que puede ser?

Código Delphi [-]
var
    oldScreen: TBitMap;
    LScreen: TBitmap;

procedure TscrServer.ScreenShot(Image: TBitmap);
var
  DC: HDC;
begin
  DC := GetDC(GetDesktopWindow);
  try
    Image.Canvas.Lock;
    Image.Width := GetDeviceCaps(DC, HORZRES);
    Image.Height := GetDeviceCaps(DC, VERTRES);
    BitBlt(Image.Canvas.Handle, 0, 0, Image.Width,
           Image.Height, DC, 0, 0, SRCCOPY);
    Image.Canvas.UnLock;
  finally
    ReleaseDC(GetDesktopWindow, DC);
  end;
end;

procedure TscrServer.SendScreen(AContext: TIdContext; cliente: word);
var
  msg: string;
  LBuffer: TBytes;
  LBytesStream: TBytesStream;
  LBitmap: TBitmap;
  LPngImage: TPngImage;
begin
  // Crear bitmap
  LBitmap := TBitmap.Create;
  LPngImage := TPngImage.Create;
  // Capturar pantalla
  ScreenShot(LScreen);
  // Obtener la diferencia si ya a enviado la pantalla completa
  if primeravez = True then
    LBitmap.Handle := CreateSubstractBitmap(LScreen.Canvas.Handle, oldScreen.Canvas.Handle)
  else
  begin
    LBitmap.Canvas.Lock;
    LBitmap.Assign(LScreen);
    LBitmap.Canvas.UnLock;
  end;
  LBytesStream := TBytesStream.Create;
  try
    // convertir bitmap en PNG
    LPngImage.CompressionLevel := calidadCompresion;
    LPngImage.Canvas.Lock;
    LPngImage.Assign(LBitmap);
    LPngImage.Canvas.Unlock;
    // pasa el PNG a Stream
    LPngImage.SaveToStream(LBytesStream);
    // pasar el stream al buffer de TBytes
    SetLength(LBuffer, LBytesStream.Size + 1);
    Move(LBytesStream.Bytes[0], LBuffer[0], LBytesStream.Size);
    // enviar pantalla al cliente
    if primeravez = False then
    begin
      msg := '[SCR-' + IntToStr(LBytesStream.Size) + ']';
      primeravez := True;
    end
    else
      msg := '[DIF-' + IntToStr(LBytesStream.Size) + ']';
    IdTCPServerSCRresponse(msg, AContext);
    ActualizaEstado('>SCR-SERVIDOR-' + AContext.Connection.Socket.Binding.PeerIP +
                    ':' + IntToStr(AContext.Connection.Socket.Binding.PeerPort) +
                    ' ' + msg);
    clientes[cliente].IOHandler.Write(LBuffer);
  finally
    // liberar memoria
    LBitmap.Free;
    LPngImage.Free;
    LBytesStream.Free;
    SetLength(LBuffer, 0);
  end;
  // Guardar pantalla actual para proxima comparacion
  oldScreen.Canvas.Lock;
  oldScreen.Assign(LScreen);
  oldScreen.Canvas.Unlock;
  EsperaSegundos(0.001);
end;

¿Voy pididiendo algo para picar?

Última edición por cesarsoftware fecha: 08-02-2012 a las 20:57:36.
Responder Con Cita
  #7  
Antiguo 09-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
Hoy he tenido un día muy liado. No tengo tiempo de analizar despacio tu código. Sólo decirte que CreateSubstractBitmap Crea un HBITMAP que debe ser liberado bien por la API DeleteObject, o bien por un objeto TBitmap al que se le asigna dicho HBITMAP.

Por lo demás decirte que Grandes bucles con repetición de llamadas a CreateSubstractBitmap no crean problemas con la memoria:

Código Delphi [-]
var
  i: integer;
  Bitmap: TBitmap;
begin
  for i:= 0 to 3500 do
  begin
    Bitmap:= TBitmap.Create;
    Bitmap.Handle:= CreateSubstractBitmap(Image2.Canvas.Handle, Image1.Canvas.Handle);
    Image3.Picture.Bitmap.Assign(Bitmap);
    Bitmap.Free;
  end;
end;

Saludos.
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 07:22:17.


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