"jpeg error #53" Odczyt plikow JPG z pola Blob

0

Witam,
mam problem z odczytem plikow JPG z pola Blob w MySQL, zapis robię w taki sposób:

 begin
          if ((FormatPliku = '.bmp') or (FormatPliku = '.dib')) then Dodaj_Bitmape(id)
          else if formatpliku='.jpg' then Dodaj_JPG(id)
  end;

zmienna FormatPliku jest typu string i jest również zapisywana w bazie danych.
teraz procedurki zapisu:

procedure Dodaj_Bitmape(id: integer);
var
fm: TMemoryStream;
BlobField: TBlobField;
begin
strumien.Clear;
pytania.Image1.Picture.Bitmap.SaveToStream(strumien);
test.ZQuery1.SQL.Text := 'SELECT * FROM pytania WHERE id = '+inttostr(id);
test.ZQuery1.Open;
  try
    test.ZQuery1.Edit;
    BlobField := test.ZQuery1.FieldByName('grafika') AS TBlobField;
    fm:=TMemoryStream.Create;
    fm.LoadFromStream(strumien);
    fm.Position:=0;
    BlobField.LoadFromStream(fm);
    test.ZQuery1.Post;
    showmessage(inttostr(id))
  finally
  fm.Free;
  test.ZQuery1.Close;
end;
end;

procedure Dodaj_JPG(id: integer);
var
fm: TMemoryStream;
BlobField: TBlobField;
begin
strumien.Clear;
pytania.Image1.Picture.Graphic.SaveToStream(strumien);
test.ZQuery1.SQL.Text := 'SELECT * FROM pytania WHERE id = '+inttostr(id);
test.ZQuery1.Open;
  try
    test.ZQuery1.Edit;
    BlobField := test.ZQuery1.FieldByName('grafika') AS TBlobField;
    fm:=TMemoryStream.Create;
    fm.LoadFromStream(strumien);
    fm.Position:=0;
    BlobField.LoadFromStream(fm);
    test.ZQuery1.Post;
    showmessage(inttostr(id))
  finally
  fm.Free;
  test.ZQuery1.Close;
end;
end;

obrazki ładnie zapisują się do bazy, natomiast problem tkwi w ich ponownym wyświetlaniu, oile bmp wyświetla się bez problemu poprzez:

test.ZQuery1.SQL.Text := 'SELECT grafika FROM pytania WHERE pytania.id='+inttostr(id);
test.ZQuery1.Open;
stream := TMemoryStream.Create;
stream.Clear;
while not test.ZQuery1.Eof do    //dziala nie dla jpg
  begin
  stream.Position:=0;
  (test.ZQuery1.FieldByName('grafika') as TBlobField).SaveToStream(stream);

i sprawdzenie jakiego typu jest plik

  if((FormatPliku = '.bmp') or (FormatPliku = '.dib')) then
    begin
    GraphType := gtBitmap;
    Stream.Read(GraphType, 1);
    stream.Position:=0;
    with pytania.Image1.Picture.Bitmap do
      begin
      pytania.Image1.Picture.Bitmap.LoadFromStream(stream);
      end;
    end

to już próba wyświetlenia JPG poprzez:

if ((FormatPliku = '.jpg') or (FormatPliku = '.jpeg') or (FormatPliku = '.jpe')) then
    begin
    GraphType := gtJpeg;
    Stream.Read(GraphType, buffer);
    stream.Position:=0;
    with pytania.image1.Picture.Graphic do
      begin
      bit:=TBitmap.Create;
      jpg:=TJPEGImage.Create;
      stream.Position:=0;
      jpg.LoadFromStream(stream);
      bit.Assign(jpg);
      bit.SaveToStream(stream);
      stream.Position:=0;
      pytania.Image1.Picture.Assign(bit);
      end;

kończy się komunikatem o błędzie "jpeg error #53".

Proszę Was o pomoc jak wyświetlić te JPG?

0

Mam zdaje się ten sam błąd przy trochę innej sytuacji. Odczytuję JPG z pola BLOB ale czytam nie do strumienia a do stringa. W Delphi 2010 stringi są już w unicode i podejrzewam że przy wrzucaniu danych do stringa następuje translacja niektórych zbitek bajtów na coś innego.
Radziłbym zrzucić dane które zapisujesz do pliku binarnego, następnie dane odczytane z BLOB do drugiego pliku i porównać zawartość np. w Total Commander - jeśli będą różnice na bajtach to z grubsza wiesz gdzie jest problem.
Inną przyczyną błędu może być sam typ pola w bazie - może BLOB jest tekstowy (z jakimś charsetem) zamiast binarny...

0

W MySQL nie wiem dokladnie jak to wyglada ja pracuje na PostgreSQL i meczylem sie z tym przez prawie tydzien. Uzywam do laczenia pakietu zeos i tutaj tez trzeba bylo niezle pokombinowac.

  1. W bazie pole typu jest OID
  2. Zapis zdjecia owocuje zapisaniem tylko numeru ktory jest unikalnym numerem i z tego co wyczytalem baza sobie gdzies to tam zapisuje a tu masz tylko tak jakby adres do tego zdjecia ja zapisuje to w ten sposob:
procedure TfmDodajUsera.DodajZdjecie(Sender: TObject);
var obrazek : TJPEGImage ;
    strumien : TMemoryStream ;
begin
  obrazek := TJPEGImage.Create ;
  strumien := TMemoryStream.Create ;
  try
    obrazek.Assign(Image1.Picture.Bitmap);
    obrazek.Compress ;
    obrazek.SaveToStream(strumien);
    fmMain.db.TransactIsolationLevel := tiReadCommitted; //uses ZDbcIntfs
    with qrAddImage do
     begin
       qrAddImage.ParamCheck := true ;
       SQL.Text := format('update users set zdjecie = :zdjecie where idx_osoby = %d', [spnID.Value])  ;
       ParamByName('zdjecie').LoadFromStream(strumien, ftGraphic )  ;
       ExecSQL ;
     end;
  finally
    strumien.Free ;
    obrazek.Free ;
    fmMain.db.TransactIsolationLevel := tiNone;
  end;
end;

db jest komponentem typu TZConnection i to wlasnie ten zakichany transactisolationlevel byl przyczyna moich klopotow natomiast qraddimage to TZQuery

  1. Odczyt:
procedure TGetDbImg.wczytaj_fotke();
var
    obrazek : TJPEGImage ;
    bs: TStream;
begin
  Application.ProcessMessages;
  try
    fmMain.db.TransactIsolationLevel := tiReadCommitted;

    obrazek := TJPEGImage.Create ;
    try
      fmMonitoring.imgZdjecie.Picture := nil;
      bs := TStream.Create;
      bs := fmMonitoring.qrShowUserImg.CreateBlobStream(fmMonitoring.qrShowUserImg.FieldByName('zdjecie'), bmRead);
      bs.Position := 0;
      if bs.Size > 0 then
      begin
        obrazek.LoadFromStream(bs);
        fmMonitoring.pnlImgDB.ShowCaption := False
      end;

      if not obrazek.Empty then
          fmMonitoring.imgZdjecie.Picture.Bitmap.Assign(obrazek);
    except

    end;
  finally
    obrazek.Free ;
  end;
  fmMain.db.TransactIsolationLevel := tiNone;
end;

Tak to wyglada u mnie moze wam to cos pomoze

0

trochę zmodyfikowałem swoją procedurkę i teraz wygląda tak:

procedure pokaz_jpg(id: integer);
var
Stream: TMemoryStream;
Jpg: TJpegImage;
begin
Jpg := nil;
Stream := nil;
 try
   with test.DataSource1.DataSet do
    begin
    test.ZQuery4.SQL.Text := 'Select grafika from pytania where Id='+IntToStr(Id);
    test.ZQuery4.Open;
    test.ZQuery4.First;
    Stream := TMemoryStream.Create();
    Stream.Clear;
    if not Eof then
      begin
      (FieldByName('grafika')as TBlobField).SaveToStream(Stream);
      if Stream.Size> 0 then
        begin
        // Tworzenie obrazów JPEG i załadować je ze strumienia
        Jpg := TJpegImage.Create;
        Stream.Position:=0;
        Jpg.LoadFromStream(Stream);
        // Przypisanie obrazu JEPG do właściwości Rysunek Grafika
        NowyTest.Image1.Picture.Assign(Jpg);
        end
      end
    end
 except
 NowyTest.Image1.Picture.Assign(nil);
 end;
jpg.Free;
Stream.Free;
end;

i wyświetla prawidłowo.
Potem wywołuje tylko:

procedure Pokaz_grafike(id: integer);
var
i, nr: Integer;
t_pyt:TPytania;
begin
                                   //         ODCZYT GRAFIKI
test.ZQuery1.SQL.Text := 'SELECT grafika FROM pytania WHERE pytania.id='+inttostr(id);
test.ZQuery1.Open;
stream := TMemoryStream.Create;
stream.Clear;
while not test.ZQuery1.Eof do
  begin
  stream.Position:=0;
  (test.ZQuery1.FieldByName('grafika') as TBlobField).SaveToStream(stream);
  if((FormatPliku = '.bmp') or (FormatPliku = '.dib')) then
    begin
    GraphType := gtBitmap;
    Stream.Read(GraphType, 1);
    stream.Position:=0;
    with nowytest.Image1.Picture do
      begin
      Bitmap.LoadFromStream(stream);
      end;
    end
  else
  if (FormatPliku = '.ico') then
    begin
    GraphType := gtIcon;
    Stream.Read(GraphType, buffer);
    stream.Position:=0;
    with nowytest.Image1.Picture do
      begin
      Icon.LoadFromStream(stream);
      end;
    end
  else
  if ((FormatPliku = '.emf') or (FormatPliku = '.wmf')) then
    begin
    GraphType := gtMetaFile;
    Stream.Read(GraphType, 1);
    stream.Position:=0;
    with nowytest.Image1.Picture do
      begin
      MetaFile.LoadFromStream(stream);
      end;
    end
    else
  if ((FormatPliku = '.jpg') or (FormatPliku = '.jpeg') or (FormatPliku = '.jpe')) then
    begin
    Pokaz_jpg(id);
    end;
  test.ZQuery1.Next;
  stream.Free;
end;
test.ZQuery1.Close();
end;

tylko musiałem wprowadzić do bazy dodatkową kolumnę, gdzie przechowuję format pliku graficznego, ale ważne że działa :-)

0

Jawor, powinieneś poprawić zarządzanie pamięcią - to jak obslugujesz Create i Free to jest proszenie się o kłopoty (access violation / general protection fault...).
Prawidłowa alokacja pamięci to:

obiekt := TKlasa.Create;
try

finally
obiekt.Free;
end;

W Pokaz_grafike masz przydział pamięci PRZED pętlą while a zwalniasz obiekt wielokrotnie w pętli - to mogło zadziałać tylko gdy masz 1 rekord w tabeli (albo zero rekordów i wtedy masz memory-leak).

Warto na to zwrócić uwagę.

0
rcflash napisał(a)

Jawor, powinieneś poprawić zarządzanie pamięcią - to jak obslugujesz Create i Free to jest proszenie się o kłopoty (access violation / general protection fault...).
Prawidłowa alokacja pamięci to:

obiekt := TKlasa.Create;
try

finally
obiekt.Free;
end;

W Pokaz_grafike masz przydział pamięci PRZED pętlą while a zwalniasz obiekt wielokrotnie w pętli - to mogło zadziałać tylko gdy masz 1 rekord w tabeli (albo zero rekordów i wtedy masz memory-leak).

Warto na to zwrócić uwagę.

Dzięki za zwrócenie uwagi

1 użytkowników online, w tym zalogowanych: 0, gości: 1