DBImage loading from blob
lazarus / 16-Databases
----------------------------------------------------------------------
teos · 2012-09-09 10:52
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;
----------------------------------------------------------------------
Lacak2 · 2012-09-10 06:18
Good question
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 · 2012-09-10 08:04
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.
----------------------------------------------------------------------
teos · 2012-09-10 19:55
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]
----------------------------------------------------------------------
teos · 2012-09-10 20:11
Quote from: taazz on September 10, 2012, 10:04:31 amIn 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
----------------------------------------------------------------------
taazz · 2012-09-10 21:26
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.
----------------------------------------------------------------------
goodname · 2012-09-10 22:48
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 · 2012-09-11 12:37
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
----------------------------------------------------------------------
goodname · 2012-09-11 13:16
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 · 2012-09-11 18:00
Quote from: goodname on September 11, 2012, 12:48:20 amHave 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
----------------------------------------------------------------------
Lacak2 · 2012-09-12 05:32
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 · 2012-09-12 09:05
Quote from: goodname on September 11, 2012, 03:16:49 pmThe 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.
Quoteread/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.
Quoteyour DB backups grow to be huge and more time consuming
Are the images not important?..
Quoteaccess 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 · 2012-09-12 09:56
As usual this is not a black and white situation and it depends on the
usage of the database.
Quoteat 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 · 2012-09-12 10:37
QuoteCorrect, 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.
QuoteHybrid solutions like Oracle's BFILE
Yes, NexusDB is another one that can proxy the blobs.
----------------------------------------------------------------------
goodname · 2012-09-12 13:33
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
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.
----------------------------------------------------------------------
KpjComp · 2012-09-12 15:55
QuoteI suspect that the author of the "don't put images in the
database" article deals with web pages.
That's what I do, and still use the
tag. On a website the
tag isn't just hard coded to filesystem access. Another advantage
here is then it's much easer to control other aspects of Images on
websites, like expiry dates / Cache control etc. I usually also do
some back-end processing, like auto scaling the images for thumbnail
view etc. So for dynamic websites I find DB Image Blobs much more
flexible than dumb files.
So like I said, the author of that link saying you should never put
images in database blobs, is just wrong.
----------------------------------------------------------------------
teos · 2012-09-12 21:22
Wether to store a image in a database is not only another discussion
but IMHO not relevant for my question :-) But I would not keep
separate images next to a database. AFAIK a well designed database
indeed keeps the blobs in a separate table or the developer constructs
SQL where the blob is fetched later (maybe in master-detail).
I have nothing against an extra property to keep everybody happy. What
I know for sure is that TBlobfield will not store an extra signature
in a blob field, nor read it. But I suppose tblobfield is the most
used for getting an image in a blob field.
I repeat: If you load an image from file or clipboard, the stream
allready has information about the file format.
My conclusion is that the TDBImage.Picture should load the image
itself and somebody was either not aware of the TPicture capabilities
or did not understand that the signature of a graphics file is in the
file itself.
But at this point comes the next question: how do I contact the author
of TDBImage to get the modification in the component for the next
Lazarus release?
----------------------------------------------------------------------
taazz · 2012-09-12 22:47
the problem is no the signature of the image file which might or might
not exists because in most cases it exists. The problem is that the
magic number usually is not a number but a series of numbers in
various positions on the header. Blob managing comes in blocks you
never read the entire blob in one step it has to be broken down in
multiple steps. How many steps will require depends heavily on the
underline dll (fbclient, pgXXX etc). Adding few extra bites in the
begging of the stream makes sure that what ever the block size of blob
operation is the component will know if it can load the data on the
first packet stopping any farther communication which might take a
while depending on the blob size. There are people that use the
database to store images that can be 100s of MB.
As long as there is an option to disable/enable the current behavior
that would be fine I guess. In any case you need to post a new feature
request in the bug tracker and some one that knows how to change will
be appointed to.
----------------------------------------------------------------------
KpjComp · 2012-09-12 23:17
The one problem I see with magic number's, is that in theory they
could be a potential for overlap. Eg, you could maybe have a JPeg
file that just happens to have the same signature for a BMP at the BMP
signature position, or vice versa. The problem is magic numbers are
not a standard between graphics formats.
The chances of misreading a magic number of course is small, but in
theory possible. If you add into the mix more file types, eg.
RAW/GIF/TIFF etc the chances of a overlap are even more.
This is also more than likely the reason why TPicture.LoadFromFile
first uses extension, rather than just passing along to LoadFromStream
and checking the magic numbers.
----------------------------------------------------------------------
teos · 2012-09-13 09:04
Quote from: KpjComp on September 13, 2012, 01:17:38 amThe one problem
I see with magic number's, is that in theory they could be a potential
for overlap. Eg, you could maybe have a JPeg file that just happens
to have the same signature for a BMP at the BMP signature position, or
vice versa. The problem is magic numbers are not a standard between
graphics formats.
The only flaw I see is writing a file extension as signature to a
stream. Because in the current situation the code just assumes that
the signature is right and tries to read the stream.
QuoteThe chances of misreading a magic number of course is small, but
in theory possible. If you add into the mix more file types, eg.
RAW/GIF/TIFF etc the chances of a overlap are even more.
This is also more than likely the reason why TPicture.LoadFromFile
first uses extension, rather than just passing along to LoadFromStream
and checking the magic numbers.
Yes, and using that file extension (which could also be blank or
something different than the actual graphic format) is the only flaw
TPicture.Loadfromfile has.
I wonder why we are having discussions like that: If you open a JPG
file with a text or hex editor, you see that in the first bytes of the
file the graphic format is written. And that will not be different
from the actual file type. Same applies for all other graphic formats.
I must say that I'm surprised by the doubts that graphic files have a
unique identifier in the first bytes and storing a file extension to
determine the kind of graphic is not needed by any means.
But anyway, I will post a change request. Thank you all for replying.
That is highly appericiated.
----------------------------------------------------------------------
BigChimp · 2012-09-13 09:13
Quote from: teos on September 13, 2012, 11:04:30 amI must say that I'm
surprised by the doubts that graphic files have a unique identifier in
the first bytes and storing a file extension to determine the kind of
graphic is not needed by any means.
But anyway, I will post a change request. Thank you all for replying.
That is highly appericiated.
You might want to refer to bug:
http://bugs.freepascal.org/view.php?id=22416
and of course, adding a patch will make it more likely to get this
implemented
----------------------------------------------------------------------
KpjComp · 2012-09-13 09:56
QuoteI wonder why we are having discussions like that
If you don't understand why, then I'll keep out. bye..
----------------------------------------------------------------------
teos · 2012-09-13 10:22
Quote from: KpjComp on September 13, 2012, 11:56:01 amQuoteI wonder
why we are having discussions like that
If you don't understand why, then I'll keep out. bye..
I was referring to the discussion about signatures in general, making
the mistake to think we all are experienced enough to have an idea
about graphic files and the mentioned signature.
Whatever I say or remark, it's never a personal attack. Sorry if it
looked that way.
----------------------------------------------------------------------
teos · 2012-09-13 10:24
Quote from: BigChimp on September 13, 2012, 11:13:31 amQuote from:
teos on September 13, 2012, 11:04:30 amI must say that I'm surprised
by the doubts that graphic files have a unique identifier in the first
bytes and storing a file extension to determine the kind of graphic is
not needed by any means.
But anyway, I will post a change request. Thank you all for replying.
That is highly appericiated.
You might want to refer to bug:
http://bugs.freepascal.org/view.php?id=22416
and of course, adding a patch will make it more likely to get this
implemented
I have filed a ticket. http://mantis.freepascal.org/view.php?id=22870,
now looking how to change it so the refrerence can be added.
----------------------------------------------------------------------
tonyw · 2012-10-16 14:21
I have uploaded a patch as a response to
http://bugs.freepascal.org/view.php?id=22416. This should add the
means to override the default behaviour of TDBImage and allow for
other means of identifying the BLOB image type. An example of use is
included with my response to the bug.
----------------------------------------------------------------------
José Mejuto · 2012-10-16 20:44
Quote from: KpjComp on September 13, 2012, 01:17:38 amThe chances of
misreading a magic number of course is small, but in theory possible.
If you add into the mix more file types, eg. RAW/GIF/TIFF etc the
chances of a overlap are even more.
Hello,
The graphics formats are all of them selectable using the first 16
bytes, except RAW which by definition is not s graphic format as it is
a two pieces information packet, how to interpret the data and the
data.
QuoteThis is also more than likely the reason why
TPicture.LoadFromFile first uses extension, rather than just passing
along to LoadFromStream and checking the magic numbers.
The extension was set because there were not a function to identify
graphics formats by they "magic numbers".
----------------------------------------------------------------------
KpjComp · 2012-10-17 12:05
QuoteThe graphics formats are all of them selectable using the first
16 bytes
So you know for sure that there is no potential of an overlap with all
Image formats, & using magic numbers is 100% correct.
So JPG/TIFF/GIF/PNG/PPM/PGM/PBM/PNM/WEBP/HDR/RGBE/IFF-RGFX/TGA/ILBM/IM
G/PCX/ECW/IMG/SID/CD5/FITS/PGF/XCF/PSD/PSP/CGM/SVG/CDR/AI/PPT/VML/XPS
etc/etc.. All these formats in no way could have magic numbers
embedded within them from other formats causing a mismatch, or that
every format even has a magic number marker.
Quoteexcept RAW which by definition is not s graphic format
Really, what is it then..? I'll leave you to correct the wiki entry.
-> http://en.wikipedia.org/wiki/Raw_image_format
ps. I'm not saying magic numbers is a bad, I use them myself, but just
pointed out a potential problem with using them. My take is if your
graphics format are simple, and your sticking to the common image
formats BMP/JPG/PNG etc, then having an option might be an idea!!.
----------------------------------------------------------------------
Jose Mejuto · 2012-10-17 18:53
Hello,
First, sorry about posting with different user name, the previous is
an old one that was laying around in my laptop
Quote from: KpjComp on October 17, 2012, 02:05:00 pmQuoteThe graphics
formats are all of them selectable using the first 16 bytes
So you know for sure that there is no potential of an overlap with all
Image formats, & using magic numbers is 100% correct.
So JPG/TIFF/GIF/PNG/PPM/PGM/PBM/PNM/WEBP/HDR/RGBE/IFF-RGFX/TGA/ILBM/IM
G/PCX/ECW/IMG/SID/CD5/FITS/PGF/XCF/PSD/PSP/CGM/SVG/CDR/AI/PPT/VML/XPS
etc/etc.. All these formats in no way could have magic numbers
embedded within them from other formats causing a mismatch, or that
every format even has a magic number marker.
Yes, at least up the point that you can decide which format use to
read. You can not know if it is a TIFF RLE or LZW but you know it is a
TIFF. Also you only need to know how to separate the known Lazarus
formats, the other ones are not relevant for TImage. Of course there
are some formats in that list that I'm not aware of them.
PNG: $89+'PNG'
JPG: $FF $D8 $FF $E?
GIF: GIF
TIFF: MM $00 $2A or II $2A $00 (TIFF needs more attention)
PPM/PPM/PGM/PBM/PNM/: I do not know...
Only the ones that are based in XML or alike can have some trouble as
some are zipped and needs to be unzipped (partially) to get data
inside.
QuoteQuoteexcept RAW which by definition is not s graphic format
Really, what is it then..? I'll leave you to correct the wiki entry.
-> http://en.wikipedia.org/wiki/Raw_image_format
I'm from the old school, and then the RAW "format" was a binary dump
of memory without format, hence the RAW name, and as it is a binary
dump, the first bytes could match anything. That is the RAW format
from cameras, which in fact is a bad name, as it describes the
content, not the container and there are a lot of RAW formats all of
them not compatible with each other.
Quoteps. I'm not saying magic numbers is a bad, I use them myself, but
just pointed out a potential problem with using them. My take is if
your graphics format are simple, and your sticking to the common image
formats BMP/JPG/PNG etc, then having an option might be an idea!!.
Currently LoadFromStream uses magics to use the right reader.
----------------------------------------------------------------------
KpjComp · 2012-10-17 19:54
QuoteAlso you only need to know how to separate the known Lazarus
formats
What is known?, Lazarus like Delphi has an image registration
facility. As such it can in theory handle any image format, even one
you decide to invent yourself.
QuoteCurrently LoadFromStream uses magics to use the right reader.
What else could it use?, that's what I've already pointed out. But if
you look at the LoadFromFile, you will see it uses the Extension
first, and then falls back to magic numbers. And that's likely why
currently blobs also store this information too.
Code: [Select] if Ext <> '' then
LoadFromStreamWithFileExt(Stream, Ext)
else
LoadFromStream(Stream);
Anyway, I think enough has been said. I'm sure I've made my point
about magic numbers not been perfect. Yes, and before somebody comes
out and says that extension's are not perfect, that is correct, but at
least the problem can be sorted by the user correcting it. Expecting
the image extensions to be correct really doesn't seem a big ask
anyway.
----------------------------------------------------------------------
Jose Mejuto · 2012-10-18 13:43
Quote from: KpjComp on October 17, 2012, 09:54:12 pmQuoteAlso you only
need to know how to separate the known Lazarus formats
What is known?, Lazarus like Delphi has an image registration
facility. As such it can in theory handle any image format, even one
you decide to invent yourself.
Hello,
Right.
QuoteWhat else could it use?, that's what I've already pointed out.
One year ago it simply does not work, and there were not available way
to do it.
QuoteBut if you look at the LoadFromFile, you will see it uses the
Extension first, and then falls back to magic numbers. And that's
likely why currently blobs also store this information too.
I know it, and I was opposed to that way, it should be the inverted if
(IMHO), but as it does not limit your code as one can use the
LoadFromStream directly, no problem to me.
QuoteAnyway, I think enough has been said.
Yes sure. I like the magic numbers detection which can be overridable
using events or any other mechanism.
QuoteExpecting the image extensions to be correct really doesn't seem
a big ask anyway.
Well, it is if you develop forensic software
----------------------------------------------------------------------
Jurassic Pork · 2013-08-05 06:01
hello,
is someone interested by an example of new version of tdbimage
(lazarus 1.1 svn after 1 may 2013) ?
(see screenshot in attachment)
In this example :
- Use SqlDb components.
- Sqlite3 database biolife with 5 fishes.
- The images are stored in blob field without extension at the
beginning.
With this you can view blob images with database browser editor (ex
sqlite2009pro).
- In the database there is also a field with images links (filenames).
- You can see the linked images in a Timage.
- The linked images are stored in the folder images of the project.
- You can change the images in the database :
- for Tdbimage double click on the component and choose your image.
- for Timage click on the button near the image filename.(you must
be in edit mode )
To not store the extension at the beginning of the blob an empty
procedure DBImage1DBImageWrite is used :
Code: [Select] procedure TForm1.DBImage1DBImageWrite(Sender: TObject;
S: TStream;
GraphExt: string);
begin
end;
To detect the type of graphic when reading blob , magic number
detection is used in DBImage1DBImageRead
Code: [Select] procedure TForm1.DBImage1DBImageRead(Sender: TObject;
S: TStream;
var GraphExt: string);
var val1,val2: WORD;
begin
S.Seek(0, soFromBeginning);
S.Read(val1,2);
S.Position := 2;
S.Read(val2,2);
if (val1 = $4D42) then GraphExt := 'bmp';
if (val1 = $4947) and (val2 = $3846) then GraphExt := 'gif';
if (val1 = $5089) and (val2 = $474E) then GraphExt := 'png';
if (val1 = $D8FF) and (val2 = $E0FF) then GraphExt := 'jpg';
S.Seek(0, soFromBeginning);
end;
Friendly, J.P
----------------------------------------------------------------------
BigChimp · 2013-08-05 06:34
JP, sounds like a good idea for SQLDBTutorial4 on the wiki... or
perhaps a page called TDBImage...
If you have a working demo, I think submitting it to the bugtracker as
an example for a directory $(lazarusdir)\examples\database\TDBImage\
would be very nice - Lazarus can do with some more db demos.
One thing though: is your database free of any Borland/Embarcadero
copyrighted material (images, text)? If not, perhaps time to write up
our own fish facts...
(As for the sqlite database schema: even if that doesn't fall under
the copyright exception about one single possible/logical way to do
things, it would fall under interoperability exceptions: by providing
this demo we can use/show interoperation with Delphi examples)
----------------------------------------------------------------------
BigChimp · 2013-08-05 06:44
Oh, I'm perfectly willing to help with a wiki page/article... just
don't want to start another tutorial by myself...
----------------------------------------------------------------------
Jurassic Pork · 2013-08-05 08:15
hello bigchimp,
QuoteOne thing though: is your database free of any
Borland/Embarcadero copyrighted material (images, text)?
do you think there is problem with copyright ?
1 - THe database is a sqlite3 database not an embarcadero database
2 - Even if the contents of the database have parts of original
fishfact borland demo, i don't see copyright in the pictures and the
texts (borland demo) . If Embarcadero is an call a lawyer.
----------------------------------------------------------------------
BigChimp · 2013-08-05 08:35
Hi my porcine friend,
Quote from: Jurassic Pork on August 05, 2013, 10:15:38 amdo you think
there is problem with copyright ?
Not necessarily as it always is very subjective and depends on
jurisdictions, judge/jury mood etc. However, to avoid the possibility
of the consequences in 2. happening and getting bad publicity (and
even perhaps questioning the rest of the code) I suggest we use some
fish of our own I'd be happy to come up with something.
Quote from: Jurassic Pork on August 05, 2013, 10:15:38 am1 - THe
database is a sqlite3 database not an embarcadero database
Agreed. Therefore the physical implementation of the schema is
probably different than whatever Borland used (Paradox? Interbase?)
which already differentiates them.
Also, regardless of the above: there's only a couple of ways or
perhaps "one true way" to create a properly normalized db/a good
example db so it doesn't matter if the schema is quite alike.
No problems there, I'd say.
Quote from: Jurassic Pork on August 05, 2013, 10:15:38 am2 - Even if
the contents of the database have parts of original fishfact borland
demo, i don't see copyright in the pictures and the texts (borland
demo) . If Embarcadero is an call a lawyer.
Well yes, if it were my own project I might take that chance. However,
there's more people watching and... well, what I said above.
----------------------------------------------------------------------
Jurassic Pork · 2013-08-06 13:49
hello,
i have created a new sqlite3 Database for my project. It contains
mushrooms. I haven't found jurassic mushrooms, then i have taken
deadly mushrooms. All the texts and images come from wikipedia.
Features:
- Use SqlDb components.
- Sqlite3 database DeadlyMushrooms with 5 mushrooms.
- The images are stored in blob field without extension at the
beginning.
With this you can view blob images with database browser editor (ex
sqlite2009pro).
- In the database there is also a field with images links (filenames).
- You can see the linked images in a Timage.
- The linked images are stored in the folder images of the project.
- You can change the images in the database :
- for Tdbimage double click on the component and choose your image.
- for Timage click on the button near the image filename.(you must
be in edit mode )
- Transaction commit when you click on Tdbnavigator refresh button or
on close form.
- Small pictures of the mushrooms are in the sqlite3Database. Largest
images are in files in the folder images.
In attachment a screenshot of the project.
Friendly, J.P
----------------------------------------------------------------------
BigChimp · 2014-01-10 11:37
Hi Jurassic Pork,
Haven't seen any mushrooms come up in the Lazarus examples
directory...
Just wondering if you had a chance to upload it as an example to the
bugtracker... (especially as I'm fighting a bit with dbimage myself )
Thanks,
BigChimp
----------------------------------------------------------------------
Jurassic Pork · 2014-01-10 17:37
hello bigChimp,
i have MushRooms database project in a 7zip file but it is too big for
this forum ( 260k > 250k)
where to upload it ?
Friendly J.P
----------------------------------------------------------------------
BigChimp · 2014-01-10 17:42
You can attach it to a bug report in the bug tracker as a sample
project for Lazarus db components.
----------------------------------------------------------------------
Jurassic Pork · 2014-01-10 17:56
mantis free pascal bugtracker issue 0025511
----------------------------------------------------------------------
BigChimp · 2014-01-10 18:00
Great, thanks! POsted a comment there
----------------------------------------------------------------------
Jurassic Pork · 2014-01-15 02:19
Hello BigChimp,
i have added a lazreport report in my Mushroom Database and a print
button to print the report with all the mushrooms in the database.
In each page of the report :
a title
the field common_name of the mushroom database.
the field notes of the mushroom database.
the field picture of the mushroom database (picture picture1).
the picture of the field image_link (picture picture2).
the report name is Mushroom_Report.lrf
to do that :
i have patched the laz_class.pas of the lazreport component with this
patch
new procedures in unit1.pas
Code: [Select]procedure TForm1.frReport1DBImageRead(Sender: TObject;
S: TStream;
var GraphExt: string);
var val1,val2: WORD;
begin
S.Seek(0, soFromBeginning);
S.Read(val1,2);
S.Position := 2;
S.Read(val2,2);
if (val1 = $4D42) then GraphExt := 'bmp';
if (val1 = $4947) and (val2 = $3846) then GraphExt := 'gif';
if (val1 = $5089) and (val2 = $474E) then GraphExt := 'png';
if (val1 = $D8FF) and (val2 = $E0FF) then GraphExt := 'jpg';
S.Seek(0, soFromBeginning);
end;
procedure TForm1.frReport1EnterRect(Memo: TStringList; View: TfrView);
begin
if View.Name = 'Picture2' then
if DBEdit1.Text <> '' then
TFrPictureView(View).Picture.LoadFromFile(ExtractFilePath(ParamStr(0))
+
'images' + DirectorySeparator + DBEdit1.Text);
end;
original source of the database with the sqlite3 Imagetest.db3
database is here
the modified or added files in attachments
Friendly J.P
----------------------------------------------------------------------
Jurassic Pork · 2014-01-16 02:12
they are some errors in the project.
A new archive of the project is available here
you need to register to see and download attachments in this forum.
here the new readme of the project :
QuoteMushRoomsDatabase by Jurassic Pork - January 2014
Features:
- Use SqlDb and lazreport components.
- Sqlite3 database DeadlyMushrooms with 5 mushrooms.
- The images are stored in blob field without extension at the
beginning.
With this you can view blob images with database browser editor (ex
sqlite2009pro).
- In the database there is also a field with images links (filenames).
- You can see the linked images in a Timage.
- The linked images are stored in the folder images of the project.
- You can change the images in the database :
- for Tdbimage double click on the component and choose your image.
- for Timage click on the button near the image filename.(you must be
in edit mode )
- Transaction commit when you click on Tdbnavigator refresh button or
on close form.
- Small pictures of the mushrooms are in the sqlite3Database. Largest
images are in files in the folder images.
- Print button to print all the mushrooms (lazreport). On each page
you have :
a title
the field common_name of the mushroom database.
the field notes of the mushroom database.
the field picture of the mushroom database (picture picture1).
the picture of the field image_link (picture picture2).
the report name is Mushroom_Report.lrf
Notes :
Depending of your Lazarus version, you need to patch the following
files before to load and compile the project :
1 - file lazarus/lcl/dbctrls.pp and file
lazarus/lcl/include/dbimage.inc
add OnDBImageRead and OnDBImageWrite properties
2 - file lazarus/components/lazreport/source/lr_class.pas
add OnDBImageRead property
The file dbImage.patch contains the modifications in the files that
may be you have to do.
you need to recompile ide after patches.
Friendly J.P
----------------------------------------------------------------------
BigChimp · 2014-01-16 09:04
Thanks JP, will have a look!
----------------------------------------------------------------------
BigChimp · 2014-01-17 16:06
Nice example - glad it got into the Lazarus example programs
----------------------------------------------------------------------
Jurassic Pork · 2014-01-18 00:48
finally the project is now in the lazarus svn dev repository
examples/database/sqlite_mushrooms
link
you must upgrade your files with the files in the repository to have
the last updated version of the project.
the patch dbimage.patch and readme part for the patch are no longer
in this version but may be necessary for the current or old versions
of lazarus
----------------------------------------------------------------------
BigChimp · 2014-08-11 14:30
Firebird embedded support was added and the directory renamed from
examples/database/sqlite_mushrooms
to
examples/database/image_mushrooms
to better reflect current project contents/purpose.
Link:
http://svn.freepascal.org/svn/lazarus/trunk/examples/database/image_mu
shrooms