Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > API de Windows
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 27-01-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
O soy tonto o .... problema al liberar memoria

Hola compis, a ver si me podeis ayudar.
El caso es que tengo una procedure que captura la pantalla (la funcion "printscreen" que uso ultimamente esta sacada de este foro buscando la solucion a mi problema)
y la envia por tcp a un servidor, todo funciona correctamente exepto en un "pequeño" problema, no libera la ram, y mira que se lo digo, pero nada.
Toda la culpa de no liberar la memoria esta en esta funcion "LBitmap.Canvas.CopyRect(r, c, r);" Si no la pongo manda la imagen en blanco, vale, pero la manda y no gasta ni un bit de ram, pero como se la ponga me "come" megas y megas en poco segundos.
Ojo me pasa lo mismo si uso la funcion "vieja" "BitBlt(LBitmap.Canvas.Handle, 0, 0, Screen.Width, Screen.Height, GetWindowDC(GetDesktopWindow), 0, 0, SRCCOPY);"

He aqui el codigo por si quereis probar. Gracias por anticipado.

Código Delphi [-]
procedure TscrServer.SendScreen(AContext: TIdContext; cliente: word);
var
  msg: string;
  LBuffer: TBytes;
  LBitmap: TBitmap;
  LBytesStream: TBytesStream;
  LPngImage: TPngImage;
  c: TCanvas;
  r: TRect;
begin
  // crear objetos
  c := TCanvas.Create;
  c.Handle := GetWindowDC(GetDesktopWindow);
  LBitmap := TBitmap.Create;
  LPngImage := TPngImage.Create;
  LBytesStream := TBytesStream.Create;
  try
    // copiar la pantalla en la imagen bitmap
    r := Rect(0, 0, ScreenWidth, ScreenHeight);
    LBitmap.Height := ScreenHeight;
    LBitmap.Width := ScreenWidth;
    LBitmap.Canvas.CopyRect(r, c, r);
    // convertir bitmap en PNG
    LPngImage.CompressionLevel := calidadCompresion;
    LPngImage.Assign(LBitmap);
    // pasa el PNG a Stream
    LPngImage.SaveToStream(LBytesStream);
    SetLength(LBuffer, LBytesStream.Size + 1);
    Move(LBytesStream.Bytes[0], LBuffer[0], LBytesStream.Size);
    // enviar pantalla al cliente
    msg := '[SCR-' + 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
    ReleaseDC(0, c.Handle);
    FreeAndNil(r);
    FreeAndNil(LBitmap);
    FreeAndNil(LPngImage);
    FreeAndNil(LBytesStream);
    SetLength(LBuffer, 0);
  end;
  EsperaSegundos(0.001);
end;

Última edición por Casimiro Notevi fecha: 27-01-2012 a las 23:29:54.
Responder Con Cita
  #2  
Antiguo 27-01-2012
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.195
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Recuerda poner las etiquetas de código para poderlo leer cómodamente.

Respecto a tu problema, no estas liberando los objetos creados, sólo parte de ellos. Prueba de esta manera:

Código Delphi [-]
// liberar memoria
c.Free;
// No procede FreeAndNil(r);
LBitmap.Free;
LPngImage.Free;
LBytesStream.Free;
SetLength(LBuffer, 0);


Saludos.
Responder Con Cita
  #3  
Antiguo 30-01-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
Gracias por tu respuesta "escafandra"

Pero sigo igual

he probado a usar
Código Delphi [-]
 if Win32Platform = VER_PLATFORM_WIN32_NT then
    SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);

y nada, lo que parece que la memoria se llena la del sistema operativo no de la aplicación.
Quizas, si pudiera leer la pantalla de otra forma, por ejemplo leyendo los pixeles del canvas de la pantalla y pasandolos al bitmap no consuma ram, pero he probado
Código Delphi [-]
    for x := 1 to ScreenWidth do
      for y := 1 to ScreenHeight do
        LBitmap.Canvas.Pixels[x, y] := clLime;//c.Pixels[x, y];
//    LBitmap.Canvas.CopyRect(r, c, r);
y me sigue gastado toda la ram

Con esto llego a la conclusion de que no se libera la ram por parte del sistema operativo y es siempre que lleno el bitmap, osea se libera el bitmap pero el "buufer" intermedio no.
¿Como podria pasar la imagen directamente al stream?

Gracias.
Responder Con Cita
  #4  
Antiguo 30-01-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
Hola de nuevo.

Lo que he podido comprobar, es que donde "se queda" la memoria es en "errores de pagina" de la aplicación.
Esta es la vista inicial de la aplicacion "cpcomcontrol.exe"



y esta tras un medio minuto de ejecucion (manda la pantalla cada 500 ms mas o menos) ha gastado 130 mb de ram. Cuando salgo de la aplicacion se libera toda la ram.


¿Como puedo liberar los "errores de pagina"?

Gracias y perdonar por insistir pero si lo solucionamos pongo todo el codigo para que quien quiera pueda hacerse un pequeño (o grande) vnc o escritorio remoto.
Responder Con Cita
  #5  
Antiguo 30-01-2012
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.195
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
prueba a liberar así:

Código Delphi [-]
ReleaseDC(0, c.Handle);
c.Handle:= 0;
c.Free;
LBitmap.Free;
LPngImage.Free;
LBytesStream.Free;
SetLength(LBuffer, 0);

¿El Componente TPngImage es de terceros?, ¿no será esa la causa?. Prueba a mandar la imagen sin comprimir o en Jpg.

También puedes tener fugas en otro punto que no sea ese procedimiento.

Valora resolver esa tarea con la API de GDI plus.


Saludos.
Responder Con Cita
  #6  
Antiguo 30-01-2012
Avatar de cesarsoftware
cesarsoftware cesarsoftware is offline
Miembro
 
Registrado: nov 2006
Posts: 241
Poder: 18
cesarsoftware Va por buen camino
Gracias escafandra por seguir el tema.

voy a probar como dices, pero me da que no.

El componente TPngImage es de delphi igual que el jpeg o bitmap, el problema como explicaba antes no es del formato de la imagen ni de mandarlo, es cuando lleno bitmap. Ya he probado en jpeg, sin comprimir, llenarlo y no mandarlo, etc.

Código Delphi [-]
interface
uses
  Classes, Windows, SysUtils, Graphics, PngImage,
  Funciones, UnitGlobal,
  IdContext, IdBaseComponent, IdComponent, IdCustomTCPServer, IdThread, IdSync,
  IdTCPServer, IdTCPClient;

¿Por que se queda en errores de pagina?
¿Se te ocurre como mandar el LBitmap.Canvas.CopyRect(r, c, r); directamente al stream sin pasar por el bitmap o png?
La verdad es que como mejor funciona es con png, si uso jpeg se "frie" (sin recursos) en un momento, no va bien en jpeg.

y por ultimo ¿que es el GDI plus?
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

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 19:07:17
Liberar memoria Sick boy Varios 6 02-07-2005 11:11:29
problema tonto gatsu PHP 2 25-04-2005 22:41:21
Liberar Memoria JoseQ Varios 6 16-07-2004 19:49:21
Liberar Memoria JODELSA Varios 4 13-05-2003 18:39:05


La franja horaria es GMT +2. Ahora son las 18:08:22.


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