GARANTIR DESCONTO

Fórum Gravar Imagem no Firebird: Algumas Opções!! #289260

23/07/2005

0

Olá pessoal, tudo bem? Espero que sim.

Sei que já tem vários tópicos sobre isso aqui no fórum, e eu dei uma olhada em alguns, mas estou precisando de algumas considerações específicar, se for possível. Estou usando Delphi 7 + Firebird 1.5 = dbExpress. Vou numerar pra ficar melhor:

[b:9b7f98727f]1. Gravar efetivamente a imagem no BD: [/b:9b7f98727f]Bom, aqui eu gostaria de saber como gravar mesmo a imagem no banco de dados. Já tenho o campo BLOB type 2 na tabela. Eu usava antes o sistema de gravar o caminho da imagem no banco. E fiz toda estrutura pra gravar a imagem e exibir ela, agora estou mudando.

Então a idéia é, quando clicar num botão, ele executar um OpenPictureDialog e quando eu selecionar o arquivo, ele salvar a imagem no banco.

Eu tentei usar o seguinte comando, que achei aqui no fórum:

(qryCadastro.FieldByName(´arq_blob´) as TBlobField).LoadFromFile 
(OpenPictureDialog.FileName); 


Mas quando eu tento executar ele dá um problema no TBlobField e no LoadFromFile, dizendo que não sao declarados. Como posso fazer isso?

[b:9b7f98727f]2. Apagar Imagem do Banco de Dados: [/b:9b7f98727f]Tenho no programa também um botão pra apagar a imagem do Banco, caso ela tenha sido colocada erroneamente. Antes era fácil, era só apagar o Blob de texto e pronto, mas agora com a imagem gravada diretamente, como posso fazer isso?

[b:9b7f98727f]3. Alternar Entre Uma Imagem do Banco e Outra Fixa: [/b:9b7f98727f]Bom, esse caso é o último, hehe.. Eu usava esse sistema antes e gostaria de usar agora. Quando o banco não tem uma imagem selecionada, é mostrada um campo TImage como uma imagem padrão, escrito ´Sem Imagem´. Então, antes, quando o campo Blob da imagem tava vazio (texto), eu tornava o ´TImageBanco´ invisível e tornava o ´TImage´ visível, assim sempre mostrava uma imagem padrão quando o arquivo não tinha imagem. Como posso fazer isso usando o campo Blob type 2?

Agradeço qualquer ajuda deste tópico desde já..

Abraços..



Allan Elias Ramos :wink:


Aersoftware

Aersoftware

Responder

Posts

24/07/2005

Bon Jovi

1. Isto deveria compilar sim. Ou vc nem deve ter instanciado o ´qryCadastro´.

2. Pra apagar use o método Clear do TField.

3. Segue exemplo:
uses JPEG;

procedure TDMTeste.CarregaImagem(BlobField: TBlobField; Image: TImage; ImagePadrao: TImage);
var
  MemoryStream: TMemoryStream;
  JPEG: TJPEGImage;
begin
  if BlobField.IsNull then
  begin
    Image.Picture.Assign(ImagePadrao.Picture);
    Exit;
  end;

  JPEG := TJPEGImage.Create;
  MemoryStream := TMemoryStream.Create;
  try
    BlobField.SaveToStream(MemoryStream);
    MemoryStream.Seek(0, soFromBeginning);
    JPEG.LoadFromStream(MemoryStream);
    if MemoryStream.Size > 0 then
      Image.Picture.Assign(JPEG)
    else
      Image.Picture.Assign(nil);
  finally
    JPEG.Free;
    MemoryStream.Free;
  end;
end;

Ex. de uso:
  CarregaImagem(TBlobField(ClientDataSet1.FieldByName(´arq_blob´)), Image1, Image2);


Outra opção é usar DBImage, que carrega automaticamente a imagem do banco. No evento AfterScroll do DataSet vc trataria a troca pela imagem ´padrao´.


Responder

Gostei + 0

24/07/2005

Aersoftware

[quote:d5a1f3d12f=´Bon Jovi´]1. Isto deveria compilar sim. Ou vc nem deve ter instanciado o ´qryCadastro´.[/quote:d5a1f3d12f]

Olá Bon Jovi. Nesse caso, o ´qryCadastro´ seria o componente TSQLDataSet ou seria o TClientDataSet? Como estou usando o dbExpress, eu usei o TClientDataSet. Ele esta num DataModule, então ficou assim o código:

Quando o usuário clicar no botão pra carregar a imagem, ele faz isso:

  if OpImagem.Execute then
    begin
     (DmDados.ClientNacionais.FieldByName(´CAPA´) as TBlobField).LoadFromFile(OpImagem.FileName);
    end;


E o erro que dá é esse:

[Error] UCadNacionais.pas(659): Undeclared identifier: ´TBlobField´
[Error] UCadNacionais.pas(659): Undeclared identifier: ´LoadFromFile´
[Fatal Error] ProjHqmx.dpr(23): Could not compile used unit ´UCadNacionais.pas´


Eu dei uma olhada no campo ´CAPA´, que é o campo Blob pra salvar a imagem e na propriedade BlobType, ta como ´ftMemo´.. não sei se isso muda alguma coisa, mas antes, esse campo tava como Blob Text, depois mudei no Banco pra Blob Binary. Já tentei mudar esse BlobType pra ´ftBlob´ e pra ´ftTypedBinary´, mas o erro persiste.



Allan Elias Ramos :wink:


Responder

Gostei + 0

24/07/2005

Bon Jovi

Ah.. deve tá faltando unit Db no uses.

E o BlobType correto é ftBlob mesmo.


Responder

Gostei + 0

24/07/2005

Aersoftware

[quote:70350a02e3=´Bon Jovi´]Ah.. deve tá faltando unit Db no uses.

E o BlobType correto é ftBlob mesmo.[/quote:70350a02e3]

Olá Bon Jovi, obrigado. Funcionou depois que coloquei a a unit DB. Mas agora ele me dá um erro quando seleciono a imagem. É o seguinte:

´Bitmap image is not valid´


Eu já adiconei a unit Jpeg no uses e formatei o OpenPictureDialog pra exibir somente arquivos JPG ou JPEG. Geralmente os arquivos que tenho, e esse q tento colocar é extensão JPG.. O q pode ser isso?



Allan Elias Ramos :wink:


Responder

Gostei + 0

25/07/2005

Daemon

.....cara. ....opnião minha.. ..... ..apesar de existir diversas formas de se gravar imagem no banco de dados, eu aconselho profundamente que não faça isso, ao invés disso, grave no banco o caminho em diretório das imagens, e guarde essas imagens em diretórios, assim você não vai carregar o banco de dados .... .....eu já fiz esse teste com imagens de uma empresa que faz fotografia e tratamento de imagens, de cara eram dois DVDs cheios de imagens de resolução 1600x1280 ... e mesmo o sistema funcionando via remota, o sistema ficou considerávelmente mais rápido do que se fosse em banco de dados. ..... ..talvez isso ajude um pouco. ....

flws..


Responder

Gostei + 0

25/07/2005

Aersoftware

Daemon, eu já fiz isso.. na verdade, no começo dessa minha aplicação era assim. Mas como esse problema é pra mim mesmo, e eu sempre estou mexendo e modificando diretórios, isso ficou meio complicado. E, na minha opinião, guardar as imagens no diretório da aplicação dá no mesmo que gravar ela no Banco. Então estou fazendo essa opção, mas primeiramente é pra teste. Se eu não gostar, posso voltar ao antigo.

Descobri agora que o DBImage não suporta JPG, é verdade? Um formato tão comum.. Tem alguma alternativa a ele, nativa do Delphi? Eu sei q o EDBImage suporta, mas deu um problema na hora de eu instalar ele. Diz que falta um arquivo, se não me engano é o Configuration.inc. Aguém que já instalou aconteceu a mesma coisa?



Allan Elias Ramos :wink:


Responder

Gostei + 0

25/07/2005

Bon Jovi

eu aconselho profundamente que não faça isso, ao invés disso, grave no banco o caminho em diretório das imagens, e guarde essas imagens em diretórios,

Dependendo do tipo de acesso pode até ser bom. Mas se for via diretório compartilhado na rede aí pode ser furada, ficaria sem segurança, pois o usuário pode modificar ou apagar todos os arquivos diretamente pelo Windows. Outra desvantagem é que guardando em diretório vc perde a integridade referencial com os dados.

Descobri agora que o DBImage não suporta JPG, é verdade?

Suporta, segue aí exemplo:
procedure TForm1.EscolheImagem(Imagem: TDBImage);
var
  oJPEG: TJPEGImage;
  oDialogo: TOpenPictureDialog;
  oPicture: TPicture;
begin
  if not Assigned(Imagem) then
    Exit;

  if (not Assigned(Imagem.DataSource)) or (Imagem.DataField = ´´) then
    Exit;

  if not Assigned(Imagem.DataSource.DataSet) then
    Exit;

  if not (Imagem.DataSource.DataSet.Active) then
    Exit;
     
  oDialogo := TOpenPictureDialog.Create(nil);
  try
    oDialogo.Options := [ofOverwritePrompt, ofHideReadOnly, ofEnableSizing];
    oDialogo.Filter := ´Imagens (*.jpg;*.jpeg;*.bmp)|*.jpg;*.jpeg;*.bmp´;
    oPicture := TPicture.Create;
    try
      oJPEG := TJPEGImage.Create;
      try
        if oDialogo.Execute then
        begin
          oPicture.LoadFromFile(oDialogo.FileName);
          oJPEG.Assign(oPicture.Graphic);
          if not (Imagem.DataSource.DataSet.State in dsEditModes) then
            Imagem.DataSource.DataSet.Edit;
          Imagem.Picture.Graphic.Assign(oJPEG);
        end;
      finally
        FreeAndNil(oJPEG);
      end;
    finally
      FreeAndNil(oPicture);
    end;
  finally
    FreeAndNil(oDialogo);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  EscolheImagem(DBImage1);
end;



Responder

Gostei + 0

25/07/2005

Aersoftware

Amigo Bon Jovi, fico muito grato com sua ajuda. Consegui fazer carregar a imagem usando o componente EDBImage.

Mas ocorreu um erro estranho. Eu instalei o componente, tentei algumas vezes até dar certo, mas funcionou.

Quando eu coloquei ele no Form, que é igual ao DBImage, ele deu um erro na hora de salvar. Não lembro direito qual mensagem exatamente foi, mas pelo que entendi, ele dizia que não achava os componentes de acesso, que estavam no DataModule. Bom, retirei o componente, saí do projeto, abri denovo e inseri.. aí o form todo nao acha o DataModule. Fiz com que achasse e funcionou perfeito, mas um erro persiste. Eu tenho nesse form dois campos lookup, um listando grupos e outro subgrupos. de duas tabelas diferentes. Só que, o primeiro que ele deveria listar, que é o de grupos, ele fica inativo. Tem vários grupos cadastrados, mas ele nao lista nenhum. Já tentei recriar o LookUp, mas não funciona. Isso ja aconteceu comigo antes, mas nao lembro como resolver. Por acaso já aconteceu com vc? Do LookUp estar ali, mas parecer que esta desativado?



Allan Elias Ramos :wink:


Responder

Gostei + 0

26/07/2005

Aersoftware

[quote:a29d9ba298=´Bon Jovi´]Suporta, segue aí exemplo:
procedure TForm1.EscolheImagem(Imagem: TDBImage);
var
  oJPEG: TJPEGImage;
  oDialogo: TOpenPictureDialog;
  oPicture: TPicture;
begin
  if not Assigned(Imagem) then
    Exit;

  if (not Assigned(Imagem.DataSource)) or (Imagem.DataField = ´´) then
    Exit;

  if not Assigned(Imagem.DataSource.DataSet) then
    Exit;

  if not (Imagem.DataSource.DataSet.Active) then
    Exit;
     
  oDialogo := TOpenPictureDialog.Create(nil);
  try
    oDialogo.Options := [ofOverwritePrompt, ofHideReadOnly, ofEnableSizing];
    oDialogo.Filter := ´Imagens (*.jpg;*.jpeg;*.bmp)|*.jpg;*.jpeg;*.bmp´;
    oPicture := TPicture.Create;
    try
      oJPEG := TJPEGImage.Create;
      try
        if oDialogo.Execute then
        begin
          oPicture.LoadFromFile(oDialogo.FileName);
          oJPEG.Assign(oPicture.Graphic);
          if not (Imagem.DataSource.DataSet.State in dsEditModes) then
            Imagem.DataSource.DataSet.Edit;
          Imagem.Picture.Graphic.Assign(oJPEG);
        end;
      finally
        FreeAndNil(oJPEG);
      end;
    finally
      FreeAndNil(oPicture);
    end;
  finally
    FreeAndNil(oDialogo);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  EscolheImagem(DBImage1);
end;
[/quote:a29d9ba298]

Amigo Bon Jovi. Fico muito grato com a sua ajuda. Depois de instalar e desinstalar o EDBImage, ver mensagens de erro na hora de botar a imagem e etc, usando o código acima que vc postou, funcionou. Consigo agora inserir e visualizar a imagem.

O único problema que ficou foi que o LookUp trancou, mas vou abrir um novo tópico pra perguntar sobre isso, pra nao poluir esse com outro assunto.

Só gostaria de fazer mais duas perguntinhas. Tem como dar uma explicadinha nas linhas desse código acima? Eu fiquei meio perdido enquanto digitava ele, e personalizava no meu aplicativo, mas funcionou perfeitamente, na primeira tentativa. Se não for dar muito trabalho, é claro..

E a outra pergunta é, como o banco de dados, no caso o firebird, salva o nome da imagem? Ele gera um nome aleatório ou salva com o nome original do aqruivo? No caso da primeira opção, pra eu salvar com o nome original da imagem, eu teria q ter um campo de texto pra capturar esse nome?

Mais uma vez agradeço a ajuda. Obrigado.



Allan Elias Ramos :wink:


Responder

Gostei + 0

26/07/2005

Bon Jovi

Sobre o lookup, nunca vi isso, nao sei o q pode ser. Melhor postar nova msg mesmo.

Sobre o Firebird nao conheço ele nesse ponto, melhor postar num forum sobre ele. Mesmo em outro banco nunca me preocupei com isso, pois gravo o nome em um campo separado mesmo.

Segue a funcao comentada:
procedure EscolheImagem(Imagem: TDBImage);
var
  oJPEG: TJPEGImage;
  oDialogo: TOpenPictureDialog;
  oPicture: TPicture;
begin
  if not Assigned(Imagem) then  //somente pra evitar erro do programador
    Exit;

  if (not Assigned(Imagem.DataSource)) or (Imagem.DataField = ´´) then //somente pra evitar erro do programador
    Exit;

  if not Assigned(Imagem.DataSource.DataSet) then //somente pra evitar erro do programador
    Exit;

  if not (Imagem.DataSource.DataSet.Active) then //somente pra evitar erro do programador
    Exit;

  oDialogo := TOpenPictureDialog.Create(nil); //instancia um TOpenPictureDialog. Fiz isso pra função ficar mais isolada, mas prefira colocar no form direto ou deixe um sempre instanciado 
  try
    oDialogo.Options := [ofOverwritePrompt, ofHideReadOnly, ofEnableSizing]; //opções da janela de diálogo do Windows, nem lembro pq coloquei isso nao tao fazendo sentido nesse caso
    oDialogo.Filter := ´Imagens (*.jpg;*.jpeg;*.bmp)|*.jpg;*.jpeg;*.bmp´; //filtra as extensões jpg, jpeg e bmp
    oPicture := TPicture.Create; //instancia um TPicture
    try
      oJPEG := TJPEGImage.Create; //instancia um TJPEGImage
      try
        if oDialogo.Execute then //executa a janela de dialogo do Windows
        begin
          oPicture.LoadFromFile(oDialogo.FileName); //carrega o arquivo escolhido na janela de dialogo no TPicture
          oJPEG.Assign(oPicture.Graphic); //copia a imagem carregada do arquivo para o objeto do tipo TJPEGImage, se for bmp já converte pra Jpeg
          if not (Imagem.DataSource.DataSet.State in dsEditModes) then
            Imagem.DataSource.DataSet.Edit; //deixa o DataSet editável, se nao tiver

          Imagem.Picture.Graphic.Assign(oJPEG); //copia a imagem JPEG para o TDBImage que é exibido pro usuario
        end;
      finally
        FreeAndNil(oJPEG); 
      end;
    finally
      FreeAndNil(oPicture);
    end;
  finally
    FreeAndNil(oDialogo);
  end;
end;



Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar