Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Recuperando una imagen de SQL Server da error (https://www.clubdelphi.com/foros/showthread.php?t=84479)

ginkaku 23-10-2013 18:27:34

Recuperando una imagen de SQL Server da error
 
Disculpen si el tema es comun, pero he estado buscando en el foro y no logro resolver mi problema.
Estoy trabajando con imagenes en bases de datos y las inserciones las hace normalmente, pero al momento de recuperar una imagen es donde caigo en un problema:
Código:

TMemoryStream *ima = new TMemoryStream;
 ADOQuery2->Active=false;
 ADOQuery2->Active=true;
 ADOQuery2->Open();
 TGraphicField(ADOQuery2->FieldByName("imagen")).SaveToStream(ima); //<----no pasa de esta linea;
 ///
 ///
 ///
 ima->Free();

El error que me da es :
Código:

Access Violation at addres 004EF3F2 in module 'Proyect1.exe'. Read of address 00000000.
La consulta devuelve el campo imagen que es de tipo varbinay(max). Llevo toda la mañana en esto, y no logro pasar de esa linea para seguir manejando la imagen. Agracederia alguna sugerencia o solucion

ecfisa 23-10-2013 21:54:16

Hola ginkaku.

Una consulta, ¿ Que tipo de imágenes fueron guardadas en el campo "imagen" (BMP, JPG, ...) ?

Saludos :)

ginkaku 23-10-2013 23:28:28

imagenes del tipo BMP ecfisa, estoy pensando en cambiar a delphi y en cambiar tambien el gestor de bases de datos...:(. No logro recuperar la imagen es muy raro

ginkaku 24-10-2013 00:58:04

Bueno nunca hay que darse por vencido, encontre el problema. Estaba obteniendo bien la imagen de la base de datos, pero tenia que pasarlo a una variable de tipo Bitmap, para recien pasarlo a un componente TImagen. Entonces la solución fue:
Código:

void __fastcall TForm1::Button2Click(TObject *Sender)
{
    TStream *blod;
 Query2->Active=false;
 Query2->Active=true;
 Query2->First();
        blod = Query2->CreateBlobStream(Query2->FieldByName("imagen"),bmRead);
        blod->Seek(0, soFromBeginning);
        Graphics::TBitmap *aaa = new Graphics::TBitmap;<-----khaaaaaaaaan
        aaa->LoadFromStream(blod);
        Image1->Picture->Assign(aaa);
 Query2->Close();
 blod->Free();
}

Lo raro que en los temas similares, muchos resuelven el problema sin este paso intermedio. Bueee eso me hiso doler la cabeza un rato. Gracias al foro que tome informacion de muchos hilos

ecfisa 24-10-2013 01:47:08

Hola gingaku.

Te preguntaba el tipo por que TGraphic no puede saber el tipo de imagen almacenada (tanto en C++ como en Delphi). Por lo que si guardas mas de un tipo de imágen, habría que crear un campo adicional para indicarlo, poder evaluarlo y hacer la asignación correspondiente.

Volviendo al BMP :), también podes hacer:
Código:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  TBlobField* bField    = (TBlobField*)Query2->FieldByName("IMAGEN");
  TBlobStream* bStream  = new TBlobStream(bField, bmRead);
  Graphics::TBitmap* bm = new Graphics::TBitmap();

  bStream->Seek(0, soFromBeginning);
  bm->LoadFromStream(bStream);
  Image1->Picture->Assign(bm);

  delete bm;
  delete bStream;
}

Saludos :)

ginkaku 24-10-2013 06:20:50

Gracias por el codigo lo voy a revisar ahora. Disculpa ecfisa, todo funciona perfecto pero solo cuando trabajo con imagenes bmp. Bueno en realidad si logra insertar jpeg, pero es el codigo de recuperar el q me falla, obviamente por la variable Graphic::TBitmap que no acepta los jpeg, ¿que tipo de variable deberia colocar para recuperar un jpeg? Intente con TJpegImage pero no tiene LoadFromStream, la cual uso para asignar. Alguien en el foro me podria guiar?

ecfisa 24-10-2013 14:25:39

Hola ginkaku.

Una de las opciones, la mas simple a mi modo de ver, es que guardes conjuntamente con la imagen, el tipo de la misma en otro campo creado en la tabla a ese efecto.

Supongamos que tenes los campos "IMAGE" y "IMGTYPE", este último de tipo entero en los que arbitrariamente voy a considerar 0=BMP, 1=JPG, ..., entonces aprovechando el polimorfismo podrías hacer:
Código:

...
#include <jpeg.hpp>
// (y demás necesarios)

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  Graphics::TBitmap *B = new Graphics::TBitmap;
  TGraphic *G;

  switch (IBQuery1->FieldByName("IMGTYPE")->AsInteger) {
    case 0 : G = new Graphics::TBitmap; break;
    case 1 : G = new TJPEGImage; break;
    case 2 : G = new TGIFImage; break;
    //...
  }
  G->Assign(((TBlobField*)(IBQuery1->FieldByName("IMAGE"))));
  B->Assign(G);
  Image1->Picture->Bitmap->Assign(B);

  delete G;
  delete B;
}

Para el ejemplo usé componentes IBX, pero no tendría que haber inconveniente con otros.

Saludos :)

ginkaku 24-10-2013 15:39:44

v:-)vv:-)vv:-)vv:-)vv:-)vv:-)vv:-)v

Totalmente de acuerdo ecfisa, muchisimas gracias, funciona de maravilla ese codigo. Inclusive ya no tengo que usar una variable de tipo TStream, recupera perfectamente las imagenes de cualquier tipo de la base de datos y es mas entendible para mi.#:-)##:-)#
Nuevamente gracias por la pronta colaboración.


La franja horaria es GMT +2. Ahora son las 23:49:35.

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