26 setembro 2012

TMemoryStream: Resolva o problema para imagens grandes

Essa dica vai ajudar muita gente!
Já aconteceu com você de precisar transferir uma imagem (principalmente JPEG) ou qualquer outro Stream (seja via datasnap ou qualquer outro meio) e se deparar com vários erros gerados pelo Delphi? Um deles é o "Out of memory while expanding..."

Acontece que o TMemoryStream só aceita até 40kb, segundo o docwiki da embarcadero e isso é um problema sério pra nós programadores.

Mas vamos lá, sem mais, declare a função abaixo no seu código e quando for salvar ou carregar seu Stream, use-a. Vou dar exemplos abaixo.


 function CopyStream( const source: TStream ): TStream;  
 //resolve o problema de memory stream com mais de 40kb  
 var  
  BytesRead: Integer;  
  Buffer: PByte;  
 const  
  MaxBufSize = $F000;  
 begin  
  { ** Criando a instância do objeto TMemoryStream para retorno do método ** }  
  result := TMemoryStream.Create;  
  { ** Reposicionando o stream para o seu início ** }  
  source.Seek( 0, TSeekOrigin.soBeginning );  
  source.Position := 0;  
  GetMem( Buffer, MaxBufSize );  
  { ** Realizando a leitura do stream original, buffer a buffer ** }  
  repeat  
   BytesRead := Source.Read( Buffer^, MaxBufSize );  
   if BytesRead > 0 then  
    result.WriteBuffer( Buffer^, BytesRead );  
  until MaxBufSize > BytesRead;  
  { ** Reposicionando o stream de retorno para o seu início ** }  
  result.Seek( 0, TSeekOrigin.soBeginning );  
 end;  


Para usar:

  •     TempStream:= TMemoryStream.Create;  
        IMG.Graphic.SaveToStream(TempStream);  
        Result:= CopyStream(TempStream);  
    
  • TempStream = TMemoryStream
  • IMG = TPicture
  • A função retorna um TStream
Quando for dar um loadfromstream, use a função também:
  •  vFoto1.LoadFromStream(CopyStream(StreamRetorno))  
    

Desse modo, você pode enviar Streams de qualquer tamanho!

Abraço a todos!