Recent

Author Topic: DBImage loading from blob  (Read 50775 times)

teos

  • Full Member
  • ***
  • Posts: 161
DBImage loading from blob
« on: September 09, 2012, 12:52:46 pm »
Hello All,

I have a question about the DBImage component, because I read that the Lazarus DBImage is not compatible with the Delphi one. And I don't understand why the code is the way it is, introducing the problems it does, but without an (for me) obvious reason.

My tought: a TImage can load a picture from either file or stream. So it must have the logics to determine what kind of image it reads. That logic is in TPicture.

I find a few things I don't understand but I think there is a reason for doing so:
1. TDBImage.LoadPicture uses a TPicture internally but instead of TDBImage.Picture.Loadfromstream a TGraphic is created, which has to determine what kind of image to read. Why? Because the code as I modified it can read the image from the blob field without further checks, because those checks are in picture.

       try
          picture.LoadFromStream(s);
        finally
          s.Free;
        end {try}

My question: does anyone know why the TDBImage code has the extra code like below? IMHO all it does is break compatibility with Delphi...

          GraphExt :=  s.ReadAnsiString;
          if GraphExt = '' then GraphExt := 'jpg';
          gc := GetGraphicClassForFileExtension(GraphExt);
          if assigned(gc) then
            begin
            AGraphic := gc.Create;
            AGraphic.LoadFromStream(s);

            Picture.Assign(AGraphic);
            end;   
« Last Edit: September 09, 2012, 01:51:33 pm by teos »

Lacak2

  • Guest
Re: DBImage loading from blob
« Reply #1 on: September 10, 2012, 08:18:30 am »
Good question  :D
It seems, that every Image descendant supports class function IsStreamFormatSupported, which checks stream data to detect known "image signature" ... clever solution.

IMO this approach can also be used in TDBImage ...

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: DBImage loading from blob
« Reply #2 on: September 10, 2012, 10:04:31 am »
because it is a well behaved easy to check and correct if anything goes wrong and also easy to duplicate in other environments that being C/C++, delphi, rudy or java and it is far better than the one used by delphi, where an integer constant was used, were to support more image types you had  to subclass the DBIMage component it self.

In any case I find it extremely well thought. This enables not so experienced developers to use existing libraries to add support for an image type (through a dll for example) with out to much work or delving to deep in the images details and any one to debug and correct recognition problems  with out the requirement of knowing the internals of each image type which in some cases might not be public knowledge.

It is far better this way although it does create some small problems with other environments it is easy to just ignore the first X bytes of the stream and load the image as they see fit.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

teos

  • Full Member
  • ***
  • Posts: 161
Re: DBImage loading from blob
« Reply #3 on: September 10, 2012, 09:55:42 pm »
I would say that someone overlooked that there is another way to determine what kind of picture is in the stream that try to use the "GetGraphicClassForFileExtension" approach that checks for a FILE extension.

TPicture.Loadfromstream uses the same approach but based on the contents of the stream.

@Taazz: I hope you know that graphic files have a signature that is also written to the blob that TDBImage reads. I agree with your opinion. But I don't agree on the extremely well thought behaviour you think DBImage has: the error handling you mention is not there: if not everything works as expected (no extension in the stream), the DBImage does not show anything, because there is no fallback that tries to determine the image type from the stream.

And a second issue: The code as I posted, is compatible not only with other programming tools but there is no database management tool which writes the extension in a blob field. So using one of those tools or the combination of Lazarus with anything else only causes problems because of the different way lazarus handles blob images.

But besided that: I was not after the differences, I was wondering if the programmer of TDBImage missed that the TPicture he assignes the image to is perfectly capable of loading that image with a fallback. (I wondered if the code is backward compatible or makes something platform independant or whatever).

And sorry: I'm not trying to be the "know it all", running into the problem that TDBImage did not display a picture whatsoever. SQLite Expert seemed not capable of writing a readable image, so I did a little investigation, finding what caused me to post this question.

Just after changing DBImage to what I have, images are visibile when I add them from something different than TDBImage (because TBlobfield does not write that signature too..)
 
[EDIT]
And I wonder why "Removed in 0.9.29. DB control should not save/load their data from stream" is there and why.
[/EDIT]
« Last Edit: September 10, 2012, 10:05:35 pm by teos »

teos

  • Full Member
  • ***
  • Posts: 161
Re: DBImage loading from blob
« Reply #4 on: September 10, 2012, 10:11:53 pm »
In any case I find it extremely well thought. This enables not so experienced developers to use existing libraries to add support for an image type (through a dll for example) with out to much work or delving to deep in the images details and any one to debug and correct recognition problems  with out the requirement of knowing the internals of each image type which in some cases might not be public knowledge.

existing libraries won't read images added by Lazarus DBImage and won't write blob fields that Lazarus DBImage is able to read. Fun is: Lazarus TDBImage is the only with the funny file extension extra.. If there were no alternatives, OK. But there is one that takes the hassle away from the programmer. I have never looked at Delphi TDBImage sources because it works and without anything extra.

Lazarus BlobStream does not read or write the extension, so it's up to the (beginning) programmer to take care of the correct extension and the correct format of that extension in the blob field, meaning digging into dbimage.inc anyway.

I choose the out of the box solution if that's OK  :D
« Last Edit: September 10, 2012, 10:13:29 pm by teos »

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: DBImage loading from blob
« Reply #5 on: September 10, 2012, 11:26:10 pm »
I am sorry I find a bit dificult to follow probably because my head spins at the moment.

TDBImage uses TBlobStream to save image data in to Image and BLOB fields. Most databases do no an Image field type just a blob when you use the TBlobstream you can save the image data with out the extra image recognition bytes that blobimage adds and tries to find. In this form all other programs should be able to read those data and try to show them and fail because most other program support only bmp/jpg/gif and maybe png what happens if the data format is a medical image format?

Using DBImage to save and load the image from the blob field dbimage adds the extra bytes required to read the image correctly the next time and on read guides the image reading classes where to start reading to aboid problems. That's it. begging programmers do not need to know how to add support for dbimage they just use it and it works. All other programmers should either adapt or move on, so should you.

Again I find the current design elegant and to the point. it is easy to bypass if needed just dont use dbimage.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

goodname

  • Sr. Member
  • ****
  • Posts: 297
Re: DBImage loading from blob
« Reply #6 on: September 11, 2012, 12:48:20 am »
Have looked at this in the past. Decided not to use DBImage as it did not seam to work and didn't put the effort to figure out why.  Used TImage with SQLdb, afterScroll events, and TPicture.LoadFromStream.

Read something about non-standard way of identifying image type which makes the saved file incompatible with other programs reading the file. TPicture.LoadFromStream seams to use the commonly recognized magic number/signature method so saved file is compatible with other programs.

http://www.lazarus.freepascal.org/index.php/topic,17606.msg97420.html#msg97420

joseme

  • Full Member
  • ***
  • Posts: 128
    • Logosoft sistemas
Re: DBImage loading from blob
« Reply #7 on: September 11, 2012, 02:37:43 pm »
You should even consider if it is no more convenient to keep your image in a separate file rather than storing it in a blob. There are performance considerations, as stated in http://www.revsys.com/blog/2012/may/01/three-things-you-should-never-put-your-database/
My two cents  :)
un aporte a la comunidad:
http://pascalylazarus.blogspot.com/

goodname

  • Sr. Member
  • ****
  • Posts: 297
Re: DBImage loading from blob
« Reply #8 on: September 11, 2012, 03:16:49 pm »
Images in the database will likely be slower on read/write and can cause the database backup to grow large.

The article does not mention the advantages to putting images in a database.
Images are backed up with the database. There is no need to worry about unique file names. You have to go through the database to figure out what image links with what record any way.

Be aware of the pros and cons and know your system needs.

teos

  • Full Member
  • ***
  • Posts: 161
Re: DBImage loading from blob
« Reply #9 on: September 11, 2012, 08:00:12 pm »
Have looked at this in the past. Decided not to use DBImage as it did not seam to work and didn't put the effort to figure out why.  Used TImage with SQLdb, afterScroll events, and TPicture.LoadFromStream.

Read something about non-standard way of identifying image type which makes the saved file incompatible with other programs reading the file. TPicture.LoadFromStream seams to use the commonly recognized magic number/signature method so saved file is compatible with other programs.

http://www.lazarus.freepascal.org/index.php/topic,17606.msg97420.html#msg97420
Yes Tpicture reads the magic number from the stream. That is my point in this. If TPicture reads the signature why is that not the way tdbimage not using that?

Even more because my modification lets the component work like it should.
 Store images in files or blobs is another discussion. In this case I have a solution for a not working component and I wonder if that is interesting for others too :)
« Last Edit: September 11, 2012, 08:05:53 pm by teos »

Lacak2

  • Guest
Re: DBImage loading from blob
« Reply #10 on: September 12, 2012, 07:32:46 am »
Yes, IMO at lest there should be property of TDBImage which will control how image data will be streamed in/out blobs.
With extension prefix or without (then image type will be detected on signature in stream).

KpjComp

  • Hero Member
  • *****
  • Posts: 680
Re: DBImage loading from blob
« Reply #11 on: September 12, 2012, 11:05:26 am »
The article does not mention the advantages to putting images in a database.

Totally agree,..

Another advantage, is if in a C/S multi-user database if you don't store them within blobs, this means your going to have to store them somewhere else, eg. a Share.  For me this takes away DB integrity, an opens more security holes.

The reasons against that @joseme showed a link too, I actually find lame.
Quote
read/write to a DB is always slower than a filesystem
Is it?, at the end of the day if your images have to be shared in a multi-user environment, then transfer of image data is exactly the same speed, it's still going over a network.  Unless the DB engine causes massive overhead, but it shouldn't.

Quote
your DB backups grow to be huge and more time consuming
Are the images not important?.. 

Quote
access to the files now requires going through your app and DB layers
That's an advantage, not a disadvantage.  If you want to access your images via a Webserver etc, it's still easy.

ludob

  • Hero Member
  • *****
  • Posts: 1173
Re: DBImage loading from blob
« Reply #12 on: September 12, 2012, 11:56:03 am »
As usual this is not a black and white situation and it depends on the usage of the database.
Quote
at the end of the day if your images have to be shared in a multi-user environment, then transfer of image data is exactly the same speed, it's still going over a network.  Unless the DB engine causes massive overhead, but it shouldn't.
Correct, but when stored in a database, the row/table is locked for the full length of the data transfer which can affect multi-user performance. Depending on the transaction isolation, multiple temporary copies of the image can float around for rollback, versioning, etc. Some databases (fe. firebird) can grow quite quickly because of the garbage left behind.

A lot depends also on how the database is designed. A separate table for images is obviously much better than adding a blob as the 20th field in an already overloaded table. If the db supports it you can then also put that table on a different volume (tablespace) and define different backup frequency and media.

Hybrid solutions like Oracle's BFILE data type is using the best of both worlds: files are stored on a file system and are accessible as a blob through the oracle client.

KpjComp

  • Hero Member
  • *****
  • Posts: 680
Re: DBImage loading from blob
« Reply #13 on: September 12, 2012, 12:37:30 pm »
Quote
Correct, but when stored in a database, the row/table is locked for the full length of the data transfer which can affect multi-user performance.

Not the way I use them.

For starters, most access to to images inside a DB for me are Read-Only.  This means you can access the images in Snapshot transaction mode, this means there is no locking involved.  And for when locking is involved when writing, the Blob, then that's what you want anyway, if integrity is important.

Like you said, keeping images inside a separate file, is also a good idea.

Quote
Hybrid solutions like Oracle's BFILE

Yes, NexusDB is another one that can proxy the blobs.

goodname

  • Sr. Member
  • ****
  • Posts: 297
Re: DBImage loading from blob
« Reply #14 on: September 12, 2012, 03:33:42 pm »
I suspect that the author of the "don't put images in the database" article deals with web pages. In that case it makes sense to just hold a path to the file as the images will be loaded later by a <img> tag. File systems are designed to handle files. That is about all they do. A database uses the underlying file system to hold blobs. For raw read and write the best a database can hope for is to add minimal overhead.

I think that DBImage should be able to handle images using signatures as well. It looks like it would be a simple patch. The only complicated part being an option to handle backward compatibility.

 

TinyPortal © 2005-2018