I wrote an example of a Sqlite access images for @Ami_Tech. I wonder if there is a better way.
I know that AdoStream and PropertyBag can convert VB.Picture to a byte array, and I also know the following code can do similar things. But these are all too complicated. I'd like to know how to convert VB.Picture to a byte array using vbRichClient5. Thanks.
Code:
Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Function GetBitmapBits Lib "gdi32" (ByVal hBitmap As Long, ByVal dwCount As Long, lpBits As Any) As Long
Private Sub GetPictureBytes()
Dim PicBits() As Byte, PicInfo As BITMAP
GetObject Picture1.Picture, Len(PicInfo), PicInfo
ReDim PicBits((PicInfo.bmWidth * PicInfo.bmHeight * 3) - 1) As Byte
GetBitmapBits Picture1.Picture, UBound(PicBits), PicBits(0)
End Sub
Public Function ArrayToPicture(inArray() As Byte, Offset As Long, Size As Long) As IPicture
' function creates a stdPicture from the passed array
' Offset is first item in array: 0 for 0 bound arrays
' Size is how many bytes comprise the image
Dim o_hMem As Long
Dim o_lpMem As Long
Dim aGUID(0 To 3) As Long
Dim IIStream As IUnknown
aGUID(0) = &H7BF80980 ' GUID for stdPicture
aGUID(1) = &H101ABF32
aGUID(2) = &HAA00BB8B
aGUID(3) = &HAB0C3000
o_hMem = GlobalAlloc(&H2&, Size)
If Not o_hMem = 0& Then
o_lpMem = GlobalLock(o_hMem)
If Not o_lpMem = 0& Then
CopyMemory ByVal o_lpMem, inArray(Offset), Size
Call GlobalUnlock(o_hMem)
If CreateStreamOnHGlobal(o_hMem, 1&, IIStream) = 0& Then
Call OleLoadPicture(ByVal ObjPtr(IIStream), 0&, 0&, aGUID(0), ArrayToPicture)
End If
End If
End If
End Function
Last edited by dreammanor; Jan 3rd, 2018 at 04:16 PM.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
This should work - though I don't have time to test it right now...
Code:
Function PictureToBytes(pPic As StdPicture) As Byte
Dim DIB As cDIB
Set DIB = New_c.DIB
Set DIB.Picture = pPic
DIB.CopyToByteArray PictureToBytes
End Function
If you don't know where you're going, any road will take you there...
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Hi,
I don't know SQLite, but here a way to store a Picture to a Memo Field is Access
Code:
'Table structure:
' BI_ID AutoWert
' BI_Nummer Long
' BI_Bild Memo field
Option Explicit
Private Cn As New ADODB.Connection
Private Sub Command1_Click()
Dim sSQL As String
Dim Bild As String
Dim FNr As Integer
Dim i As Long
Dim Rs As New ADODB.Recordset
FNr = FreeFile
Open App.Path & "\Bild1.bmp" For Binary As #FNr
i = LOF(FNr)
Bild = Space(i)
Get #FNr, , Bild
Close #FNr
sSQL = "Select * From tbl_Bilder Where BI_Nummer < 0"
With Rs
.CursorLocation = adUseClient
.CursorType = adOpenKeyset
.LockType = adLockOptimistic
.ActiveConnection = Cn
.Open sSQL
.AddNew
.Fields("BI_Nummer").Value = 9999 'just add a No. for Picture
.Fields("BI_Bild").Value = Bild
.Update
.Close
End With
Set Rs = Nothing
MsgBox "Bild eingefügt"
End Sub
Private Sub Command2_Click()
Dim Rs As New ADODB.Recordset
Dim sSQL As String
Dim FNr As Integer
Dim mFile As String
sSQL = "Select * From tbl_Bilder Where BI_Nummer = 9999"
With Rs
.CursorLocation = adUseClient
.CursorType = adOpenKeyset
.LockType = adLockReadOnly
.ActiveConnection = Cn
.Open sSQL
If .RecordCount > 0 Then
FNr = FreeFile
mFile = App.Path & "\dummy.bmp"
Open mFile For Output As #FNr
Print #FNr, .Fields("BI_Bild").Value;
Close #FNr
Set Picture1.Picture = LoadPicture(mFile)
Kill mFile
End If
.Close
End With
Set Rs = Nothing
End Sub
Private Sub Form_Load()
With Cn
.CursorLocation = adUseClient
.Mode = adModeShareDenyNone
.Provider = "Microsoft.Jet.OLEDB.4.0"
.ConnectionString = "Data Source=" & App.Path & "\Bilder.mdb"
.Open
End With
Command1.Caption = "Save Picture"
Command2.Caption = "Load Picture"
End Sub
regards
Chris
to hunt a species to extinction is not logical !
since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Thank you, ChrisE. I know that adoDB (adoStream) can convert an image to a byte array and save it to the Sqlite Mem (Blob) field. RC5 is the most convenient and powerful tool for working with Sqlite DB, so I guess there should be a very easy way to implement SQlite image storage.
In addition, things can be complicated by caching image data with temporary physical files.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by dreammanor
Thank you, ChrisE. I know that adoDB (adoStream) can convert an image to a byte array and save it to the Sqlite Mem (Blob) field. RC5 is the most convenient and powerful tool for working with Sqlite DB, so I guess there should be a very easy way to implement SQlite image storage.
In addition, things can be complicated by caching image data with temporary physical files.
where did I use adoStream ?
regards
Chris
to hunt a species to extinction is not logical !
since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by dreammanor
I'd like to know how to convert VB.Picture to a byte array using vbRichClient5.
There should never be a need to do so in this case (since a VB-StdPicture is inferior to a cCairoSurface, which becomes available with the RC5).
A VB.PictureBox should (if used at all) only be considered as a "Rendering-Endpoint" (fed from a cCairoSurface) - and not the other way around.
In addition - when storing Images in a DB, always store them as Blobs in their "native Image-Format" (their RawByte-format, as they are stored in the FileSystem).
As soon, as you are trying to serialize them into e.g. VB6-PropertyBag-Format, you will (without need) establish as platform-dependency.
Just store the RawBytes of the Image in question - and be done with it.
Ok, have taken a look at your code ... here a few additional comments:
- don't use any of the old VB-File- or Directory-Functions (e.g. you used Dir() to check for the existence of a File)
.. please use the (fully unicode-aware) File-Functions behind New_c.FSO instead (e.g. New_c.FSO.FileExists(...))
- don't instantiate RC5-Objects with VBs own 'New' Keyword - please use New_c.Connnection instead
.. (this will make it much easier, to turn an RC5-using App into a "regfree-deployable" one
ScreenShot of the App in SaveToDB-mode (using the Unicode-aware RC5-FileOpen-Dialogue... please note the chinese Image-FileName of the current Selection):
ScreenShot of the App in LoadImageFromDB-mode (using the Unicode-aware Grid-Widget from vbWidgets.dll):
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by ChrisE
where did I use adoStream ?
You didn't - but the adoStream is one of the methods, to read ByteArray-content from Files which have Unicode-Chars in their FilePath.
(the OP is on a chinese locale).
VBs old File- Open/Read/Write commands are not Unicode-aware (and should not be used for "internationally deployed Apps").
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
ah right,
(the OP is on a chinese locale).
missed that
regards
Chris
to hunt a species to extinction is not logical !
since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by Schmidt
There should never be a need to do so in this case (since a VB-StdPicture is inferior to a cCairoSurface, which becomes available with the RC5).
A VB.PictureBox should (if used at all) only be considered as a "Rendering-Endpoint" (fed from a cCairoSurface) - and not the other way around.
In addition - when storing Images in a DB, always store them as Blobs in their "native Image-Format" (their RawByte-format, as they are stored in the FileSystem).
As soon, as you are trying to serialize them into e.g. VB6-PropertyBag-Format, you will (without need) establish as platform-dependency.
Just store the RawBytes of the Image in question - and be done with it.
Olaf, thank you for your detailed reply and wonderful example. I fully agree with what you have said, only files and RawByte-format binary data are used to store images to the database, not using VB.PictureBox. I know that cCairoSurface is much more powerful than VB.PictureBox, but VB.PictureBox is the basic control of VB6 and many people are accustomed to using VB.PictureBox to do something. If RC5 is able to convert a VB.StdPicture to a byte array, that would certainly greatly facilitate their work.
I've been using RC5 to deal with SqliteDB for a long time, but I never knew how RC5 converted a VB.StdPicture to a byte array, so I've been using the FarPoint.SpreadSheet functions to do the same job:
Code:
Function LoadFromBuffer(Buff) As Boolean
Function LoadFromFile(FileName As String) As Boolean
Function LoadPicture(FileName As String, PictType As PictureTypeConstants) As StdPicture
Function LoadPictureBuffer(Buffer, Size, PictType As PictureTypeConstants) As StdPicture
Function LoadResPicture(hInstance As Long, ResourceName As String, ResourceType As String, PictType As PictureTypeConstants) As StdPicture
Function LoadTabFile(FileName As String) As Boolean
Function LoadTextFile(FileName As String, CellDelim As String, ColDelim As String, RowDelim As String, Flags As LoadTextFileConstants, LogFile As String) As Boolean
Function SavePicture(Picture As StdPicture, FileName As String, PictType As PictureTypeConstants) As Boolean
Function SavePictureBuffer(Picture As StdPicture, PictType As PictureTypeConstants, Buffer, Size) As Boolean
Function SaveTabFile(FileName As String) As Boolean
Function SaveTabFileU(FileName As String) As Boolean
Function SaveToBuffer()
Function SaveToFile(FileName As String, DataOnly As Boolean) As Boolean
In the future, I'll try to gradually replace VB.PictureBox and GDI drawings with cCairoSurface, but this process will take some time to complete because many old systems need to be maintained.
Originally Posted by Schmidt
Ok, have taken a look at your code ... here a few additional comments:
- don't use any of the old VB-File- or Directory-Functions (e.g. you used Dir() to check for the existence of a File)
.. please use the (fully unicode-aware) File-Functions behind New_c.FSO instead (e.g. New_c.FSO.FileExists(...))
- don't instantiate RC5-Objects with VBs own 'New' Keyword - please use New_c.Connnection instead
.. (this will make it much easier, to turn an RC5-using App into a "regfree-deployable" one
Very good advice, much appreciated.
Last edited by dreammanor; Jan 4th, 2018 at 06:59 AM.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by dreammanor
If RC5 is able to convert a VB.StdPicture to a byte array, that would certainly greatly facilitate their work.
As Olaf said byte array in your case will be platform/app dependant image file format. No need for this constraint unless this new format is better than most existing image formats.
So basicly you want a VB.StdPicture to BMP, JPG or PNG "byte arrays" and this has been flogged to death in these forums. This and preserving/handling alpha channel in StdPicture icon hack whatever is one the most discussed topics here.
Please don't use PropertyBags to "serialize" StdPictures -- the size overhead is 100%. Please don't use ADODB.Streams for anything (unless forced) -- speed is abysmal.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by wqweto
As Olaf said byte array in your case will be platform/app dependant image file format. No need for this constraint unless this new format is better than most existing image formats.
So basicly you want a VB.StdPicture to BMP, JPG or PNG "byte arrays" and this has been flogged to death in these forums. This and preserving/handling alpha channel in StdPicture icon hack whatever is one the most discussed topics here.
Please don't use PropertyBags to "serialize" StdPictures -- the size overhead is 100%. Please don't use ADODB.Streams for anything (unless forced) -- speed is abysmal.
cheers,
</wqw>
Yes, I agree with you. In my own projects, the FarPoint.SpreadSheet byte array and image manipulation functions are used to instead of adoStream and PropertyBag. But in the example I wrote for @Ami_Tech, I couldn't find a good method to convert a StdPicture to a byte array. Perhaps @Ami_Tech should also accept you and Olaf's advice, using only files and RawByte-format binary data to store images into the database.
Why I've been using FarPoint SpreadSheet, because I still can't found a replacement for it. RC5 can replace almost all Microsoft components and third-party components, but in the short term, it can't replace FarPoint.SpreadSheet. Developing a new SpreadSheet using RC5 and vbWidget may be a good choice, but the workload is too high。
Of course, my focus in the future will gradually shift to Web applications and Cloud-Database, SpreadSheet applications will gradually be reduced.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by ColinE66
This should work - though I don't have time to test it right now...
Code:
Function PictureToBytes(pPic As StdPicture) As Byte
Dim DIB As cDIB
Set DIB = New_c.DIB
Set DIB.Picture = pPic
DIB.CopyToByteArray PictureToBytes
End Function
If the above source code could work, that would greatly facilitate many people's work.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by dreammanor
If the above source code could work, that would greatly facilitate many people's work.
Colins Code (here with a slight correction, adjusting the return-type to a Byte-Array) does work:
Code:
Function StdPicToBytes(StdPic As StdPicture) As Byte()
Dim DIB As cDIB
Set DIB = New_c.DIB(, , StdPic)
DIB.CopyToByteArray StdPicToBytes
End Function
... but cDIB.CopyToByteArray was not intended for "serialization into a one-dimensional ByteArray-Stream" -
instead, the Method fills a "self-describing two-dimensional ByteArray-DIB-replacement for 24Bit-ImageContent" - and as such:
- it can be stored in a Collection or elsewhere
- can describe its own (DIB) Pixel-dimensions over (UBound(B ,1) + 1) \ 3 and UBound(B, 2) +1
- would be less resource-intensive than a DIB (not needing any GDI-Handle)
- and can also be used directly in Image-Manipulation-Loops, as the following simple example shows:
Code:
Option Explicit
Private Sub Form_Load()
Set Picture = LoadPicture("c:\temp\background.jpg") 'load an Image into the Forms Picture-Prop
Show
MsgBox "a Darken-Operation follows..."
Set Picture = Darken(StdPicToBytes(Picture), 0.5).Picture
End Sub
Function StdPicToBytes(StdPic As StdPicture) As Byte()
New_c.DIB(, , StdPic).CopyToByteArray StdPicToBytes
End Function
Function Darken(B() As Byte, ByVal Factor As Double) As cDIB
Dim dx As Long, dy As Long, x As Long, y As Long
dx = (UBound(B, 1) + 1) \ 3: dy = (UBound(B, 2) + 1) 'get the Pixel-Dimensions from B()
For y = 0 To dy - 1: For x = 0 To dx * 3 - 1 Step 3 '<- note the needed Step 3
B(x + 0, y) = B(x + 0, y) * Factor 'influence the Blue-Channel
B(x + 1, y) = B(x + 1, y) * Factor 'influence the Green-Channel
B(x + 2, y) = B(x + 2, y) * Factor 'influence the Red-Channel
Next x, y
Set Darken = New_c.DIB(dx, dy) 'create a new DIB-Container-Object with the same Dimensions
Darken.CopyFromByteArray B '... and copy the darkened Array-Content over
End Function
As to your "serialization-question" (into a one-dimensional ByteArray) - let's make a deal:
- I show you how to convert a VB-StdPic-Object to a Cairo-Surface (from which you can serialize to PNG- or JPG-ByteArrays easily)
- and you explain to me in more detail - with a small code-example, why you would need this (because I cannot really see, where that would come in handy)
Code:
Option Explicit
Private Sub Form_Load()
Set Picture = LoadPicture("c:\temp\background.jpg")
'convert the StdPicture to a CairoSurface - and place it back in the Picture-Prop
Set Picture = StdPicToSurface(Picture).Picture
End Sub
Function StdPicToSurface(StdPic As StdPicture) As cCairoSurface
Dim DIB As cDIB: Set DIB = New_c.DIB(, , StdPic) 'create an RC5-DIBObj from the StdPic
Set StdPicToSurface = Cairo.CreateWin32Surface(DIB.dx, DIB.dy) 'ensure the Dest-Surface
DIB.DrawTo StdPicToSurface.GetDC 'hDC-based Blitting from DIB to CairoSurface
'normally we would be finished here - but the above Blt-Op left out the Alpha-Channel,
Dim CC As cCairoContext: Set CC = StdPicToSurface.CreateContext
CC.Operator = CAIRO_OPERATOR_DEST_ATOP '...so we have to ensure one with a Paint-Op,
CC.Paint 1, Cairo.CreateSolidPatternLng(0, 1) '<- which sets the Alpha-Channel to "fully opaque"
End Function
Olaf
Last edited by Schmidt; Jan 6th, 2018 at 06:46 AM.
Reason: adjusted the Darken-Loop to respect Padding
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by Schmidt
...
... but cDIB.CopyToByteArray was not intended for "serialization into a one-dimensional ByteArray-Stream" -
instead, the Method fills a "self-describing two-dimensional ByteArray-DIB-replacement for 24Bit-ImageContent" - and as such:
- it can be stored in a Collection or elsewhere
- can describe its own (DIB) Pixel-dimensions over (UBound(B ,1) + 1) \ 3 and UBound(B, 2) +1
- would be less resource-intensive than a DIB (not needing any GDI-Handle)
- and can also be used directly in Image-Manipulation-Loops, as the following simple example shows:
...
Olaf
Very nice, RC5 is powerful indeed. I modified the StdPicToBytes method to serialize StdPicture:
Code:
Function StdPicToBytes_New(StdPic As StdPicture) As Byte()
Dim Surface As cCairoSurface
Set Surface = StdPicToSurface(StdPic)
'Surface.WriteContentToJpgByteArray StdPicToBytes_New
Surface.WriteContentToPngByteArray StdPicToBytes_New
End Function
Function StdPicToSurface(StdPic As StdPicture) As cCairoSurface
Dim DIB As cDIB
Set DIB = New_c.DIB(, , StdPic) 'create an RC5-DIBObj from the StdPic
Set StdPicToSurface = Cairo.CreateWin32Surface(DIB.dx, DIB.dy) 'ensure the Dest-Surface
DIB.DrawTo StdPicToSurface.GetDC 'hDC-based Blitting from DIB to CairoSurface
'normally we would be finished here - but the above Blt-Op left out the Alpha-Channel,
Dim CC As cCairoContext
Set CC = StdPicToSurface.CreateContext
CC.Operator = CAIRO_OPERATOR_DEST_ATOP '...so we have to ensure one with a Paint-Op,
CC.Paint 1, Cairo.CreateSolidPatternLng(0, 1) '<- which sets the Alpha-Channel to "fully opaque"
End Function
Last edited by dreammanor; Jan 8th, 2018 at 04:01 AM.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by Schmidt
As to your "serialization-question" (into a one-dimensional ByteArray) - let's make a deal:
- I show you how to convert a VB-StdPic-Object to a Cairo-Surface (from which you can serialize to PNG- or JPG-ByteArrays easily)
- and you explain to me in more detail - with a small code-example, why you would need this (because I cannot really see, where that would come in handy)
...
Olaf
IMO, it's very userful to serialize VB.StdPicture. VB.StdPicture is heavily used in VB programming, and these StdPictures often need to be stored in a database or file. Cairo is a completely new feature for many VB developers, and they are afraid to rush to use it. If using Cairo to precess VB.StdPicture (serialization, darkening, brightening, adding alpha-channel, drawing, etc.), many VB developers will gradually accept Cairo and more and more people will love and use RC5.
My software uses VB.PictureBox extensively. For example, I ofen need to copy pictures from Microsoft Word-Doc or web pages to the clipboard, then paste them into a VB.PictureBox and finally save the PictureBox.Picture into the database.
Code:
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
If Shift = 2 And KeyCode = vbKeyV Then
PastePictureFromClipboard
End If
End Sub
Private Sub PastePictureFromClipboard()
Dim objPicture As StdPicture
Set objPicture = Clipboard.GetData()
If objPicture.Handle <> 0 Then
Picture1.Picture = objPicture
End If
End Sub
In addition, if WriteContentToBmpByteArray method could be added to the vbRichClient5.cCairoSurface, that would be great. RC5 is really a great and magical product, thank you, Olaf.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by wqweto
So basicly you want a VB.StdPicture to BMP, JPG or PNG "byte arrays" and this has been flogged to death in these forums.
I agree.
All we need is a handful of API calls for extended capabilities. Here is an example that creates a series of images and stores them in a database as PNG images. Then it plays them back:
Not much to it, no 3rd party dependencies required if you use a Jet MDB like this. These databases even have support on Android, Linux, etc. via Jackcess.
Recorder.ctl:
Code:
Option Explicit
Private StickmanX As Long
Private DeltaX As Long
Private Counter As Long
Private Connection As ADODB.Connection
Private Recordset As ADODB.Recordset
Public Event Finished()
Public Sub Run()
Extender.Move 0, 0
Extender.Visible = True
BackColor = &HFFFFE0
On Error Resume Next
Kill "DB.mdb"
On Error GoTo 0
With CreateObject("ADOX.Catalog")
.Create "Provider=Microsoft.Jet.OLEDB.4.0;" _
& "Jet OLEDB:Engine Type=5;" _
& "Data Source='DB.mdb';" _
& "Mode=Share Exclusive"
Set Connection = .ActiveConnection
End With
Connection.Execute "CREATE TABLE Movie(" _
& "ID IDENTITY CONSTRAINT pkID PRIMARY KEY," _
& "Frame IMAGE)", _
, _
adCmdText Or adExecuteNoRecords
Set Recordset = New ADODB.Recordset
With Recordset
.CursorLocation = adUseServer
Set .ActiveConnection = Connection
.Properties("Append-Only Rowset").Value = True
.Open "Movie", , adOpenForwardOnly, adLockOptimistic, adCmdTableDirect
End With
DrawFrame
SaveFrame
Counter = 2
DeltaX = 5
Timer1.Enabled = True
End Sub
Private Sub DrawFrame()
Cls
DrawWidth = 1
FillStyle = vbFSSolid
Line (0, 160)-(319, 239), &H80FF80, BF
ForeColor = &HC0FFFF
FillColor = &HFFFF&
DrawWidth = 3
Circle (260, 40), 25
DrawWidth = 3
Line (StickmanX + 20, 120)-(StickmanX + 20, 170), vbBlue
Line (StickmanX, 130)-(StickmanX + 40, 130), vbBlue
Line (StickmanX + 20, 170)-(StickmanX, 190), vbBlue
Line (StickmanX + 20, 170)-(StickmanX + 40, 190), vbBlue
DrawWidth = 1
ForeColor = &H404080
FillColor = &HC0E0FF
Circle (StickmanX + 19, 109), 12
End Sub
Private Sub SaveFrame()
Recordset.AddNew "Frame", PicBytes.SavePicture(Image, fmtPNG)
End Sub
Private Sub Timer1_Timer()
StickmanX = StickmanX + DeltaX
DrawFrame
SaveFrame
If StickmanX = 280 Then
DeltaX = -5
ElseIf StickmanX = 0 Then
Counter = Counter - 1
If Counter > 0 Then
DeltaX = 5
Else
Timer1.Enabled = False
Extender.Visible = False
Recordset.Close
Connection.Close
RaiseEvent Finished
End If
End If
End Sub
Last edited by dilettante; Jan 7th, 2018 at 11:01 AM.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Hi dilettante, thank you for your reply. Your source code is very interesting. This is a good solution for AccessDB, but AccessDB has caused me too much painful memories and I rarely use AccessDB now. I don't know now whether Microsoft has solved the problem of data loss caused by AccessDB damaging. SqliteDB almost never goes wrong, just as MS SQLServer almost never makes a mistake, so I prefer to use SqliteDB.
However, even so, I can still learn a lot from your code, thank you, dilettante.
Last edited by dreammanor; Jan 8th, 2018 at 03:52 AM.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by dilettante
Here is an example that creates a series of images and stores them in a database as PNG images. Then it plays them back:
One could (with about the same amount of code) of course implement a real Scene-Recorder/Player,
which works BackGround-independent and in a better performance, looking like that:
So one has to decide for himself, whether to use a modern DB- and graphics-engine,
or if "sticking to drawing stick-mans" is the way to go with VB6...
Originally Posted by dilettante
Not much to it, no 3rd party dependencies required if you use a Jet MDB like this.
As already mentioned in the other thread - MS-COM-dependencies can break your App at any time
with the next MS-System-Updates (this happened already in the past in case of ADO/JET).
SQLite is a more powerful and faster alternative to ADO/JET - and available over
the RC5-COM-wrapper for over a decade now.
Originally Posted by dilettante
These databases even have support on Android, Linux, etc. via Jackcess.
Jackcess does support only a kind of "looping over existing table-content" and:
- is dog-slow whilst doing that ...
- but worse - it does not support the execution of any SQL
So, no - bad recommendation that.
A JDBC/SQLite implementation performs *much* better - and resembles ADO-Rs-usage far more (Java-code-wise).
Out of interest I just did a little performance-test in my Java-IDE against the newest Jackcess-version
(using a loop over the Orders-Table from NWind.mdb - then doing the same thing with JDBC-SQLite on a NWind.db-file)
Here is the results:
Code:
> run TestDBaccess
Jackcess-MDB Results:
timing: 204.2 ms
records: 830, last ID: 11077
JDBC-SQLite Results:
timing: 3.5 ms
records: 830, last ID: 11077
>
For comparison, here the VB6-results over the appropriate COM-libs:
Code:
ADO/JET Results:
timing: 4,3msec
records: 830, last ID: 11077
RC5/SQLite Results:
timing: 2,1msec
records: 830, last ID: 11077
So. both SQLite-versions outperform the MDB-based ones - and in case of Jackcess by a huge margin (about factor 100).
For those interested - here is the Java-testcode I was using:
Code:
// Jackcess-MDB specific imports
import java.io.File;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.Table;
import com.healthmarketscience.jackcess.Row;
import com.healthmarketscience.jackcess.CursorBuilder;
import com.healthmarketscience.jackcess.Cursor;
// JDBC-SQLite specific imports
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class TestMDBaccess {
public static void main(String[] args) {
try {
long startTime;
// Jackcess-MDB related part (let's open the FileDB first)
Database db = DatabaseBuilder.open(new File("NWind.mdb"));
startTime = System.nanoTime(); // let's time the Table-Opening and the Enumeration
Table table = db.getTable("Orders");
Cursor cursor = CursorBuilder.createCursor(table);
short counter=0; Object ID=null; // just two variables, which we change inside the iteration-loop
for(Row row : cursor) { // fastest way to iterate over the Table is a cursor-based enumeration
counter++;
ID = row.get("OrderID"); //just to access one single Col-Field whilst iterating over the Rows
}
System.out.println("Jackcess-MDB Results:");
System.out.println("timing: " + ((System.nanoTime()-startTime) / 100000)/10. + " ms" );
System.out.println("records: " + counter + ", last ID: " + ID );
// JDBC-SQLite related part (let's open the FileDB first)
Connection Cnn = DriverManager.getConnection("jdbc:sqlite:NWind.db");
startTime = System.nanoTime(); // let's time the Table-Request and the Enumeration
Statement Cmd = Cnn.createStatement();
ResultSet Rs = Cmd.executeQuery("Select * From Orders");
int OrderID=0; counter=0;
while (Rs.next()) { // loop through the result-set
counter++;
OrderID = Rs.getInt("OrderID"); //just to access one single Col-Field whilst iterating over the Records
}
if (Cnn != null) Cnn.close(); // close the DB-Connection again
System.out.println("JDBC-SQLite Results:");
System.out.println("timing: " + ((System.nanoTime()-startTime) / 100000)/10. + " ms" );
System.out.println("records: " + counter + ", last ID: " + OrderID );
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Olaf
Last edited by Schmidt; Jan 9th, 2018 at 02:06 AM.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by dreammanor
For example, I ofen need to copy pictures from Microsoft Word-Doc or web pages to the clipboard, then paste them into a VB.PictureBox and finally save the PictureBox.Picture into the database.
Well, the RC5 has an (Unicode-aware!) ClipBoard-Class, which besides Text, RTF, HTML and Unicode-FileContainer support,
can also hand-out already converted Image-Surfaces (even those with AlphaChannels, which e.g. FireFox supports on Image-Copy)
Code:
Option Explicit
Private ChkPat As cCairoPattern
Private Sub Form_Load()
KeyPreview = True
Set ChkPat = CreateCheckerPattern
End Sub
Private Sub Form_KeyUp(KeyCode As Integer, Shift As Integer)
If Shift = 2 And KeyCode = vbKeyV Then PastePicture New_c.Clipboard.GetImageSurface, Picture1
End Sub
Private Sub PastePicture(Srf As cCairoSurface, PB As VB.PictureBox)
If Srf Is Nothing Then Exit Sub 'if there was no Image in the ClipBoard, we get passed Nothing
With Cairo.CreateSurface(ScaleX(PB.Width, PB.ScaleMode, 3), ScaleX(PB.Height, PB.ScaleMode, 3)).CreateContext
.Paint 1, ChkPat 'draw the background-checker-pattern (in case we got PNGs)
.RenderSurfaceContent Srf, 0, 0, .Surface.Width, .Surface.Height, , , True 'render the passed Srf so that it fits into the PBox
Set PB.Picture = .Surface.Picture
End With
'now do additional Operations with the Pasted Srf-Variable (which still has its original dimensions)
' Srf.WriteContentToPngByteArray B ' <- now you can store ByteArray B in a DB
End Sub
Function CreateCheckerPattern(Optional ByVal Size& = 8, Optional ByVal Color1& = vbWhite, Optional ByVal Color2& = &HDDDDDD) As cCairoPattern
With Cairo.CreateSurface(2 * Size, 2 * Size).CreateContext
.Paint 1, Cairo.CreateSolidPatternLng(Color1) 'fill the entire Mini-Surface with Color1
.Rectangle 0, 0, Size, Size 'now, to paint over the BackColor we define a top-left rectangle
.TranslateDrawings Size, Size 'diagonal shift of the coords, to ensure the offset for the...
.Rectangle 0, 0, Size, Size 'final bottom-right-rectangle (which due to the above line can use the same coord-arguments)
.Fill , Cairo.CreateSolidPatternLng(Color2) 'fill the two Rectangle-Paths with Color2
Set CreateCheckerPattern = .Surface.CreateSurfacePattern 'ensure the return-value (creating a Pattern from the small Surface)
CreateCheckerPattern.Extend = CAIRO_EXTEND_REPEAT 'with this Pattern-Property we can ensure a kind of "Brush" when larger areas are filled
End With
End Function
Here is the result of a PNG-image (which was copied directly from FireFox) then pasted, size-adapted and rendered into a VB-PictureBox using the above code:
As you see in the comments above - after the rendering-op went through, you have still the original Srf-Object available
(not containing the Checker-Pattern-BackGround - and still in its original size) - and serialization into a ByteArray
from a CairoSurface (then storing it in a DB) - that was already covered I think.
So, still not a really convincing example from your side, why one would need the PictureBox-to-CairoSurface-direction.
Originally Posted by dreammanor
if WriteContentToBmpByteArray method could be added to the vbRichClient5.cCairoSurface, that would be great.
Why would you need that (when PNG is supported - being a nice, and losless compression-format for Bitmaps).
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by Schmidt
Why would you need that (when PNG is supported - being a nice, and losless compression-format for Bitmaps).
Olaf
In order to be compatible with historical data, because all my historical data is saved as bmp files (jpg format will distort a picture). I guess many others will also save their images as compressed bmp files.
Re: How to use vbRichClient5 to convert VB.Picture to a byte array?
Originally Posted by Schmidt
Well, the RC5 has an (Unicode-aware!) ClipBoard-Class, which besides Text, RTF, HTML and Unicode-FileContainer support,
can also hand-out already converted Image-Surfaces (even those with AlphaChannels, which e.g. FireFox supports on Image-Copy)
...
...
Here is the result of a PNG-image (which was copied directly from FireFox) then pasted, size-adapted and rendered into a VB-PictureBox using the above code:
...
...
As you see in the comments above - after the rendering-op went through, you have still the original Srf-Object available
(not containing the Checker-Pattern-BackGround - and still in its original size) - and serialization into a ByteArray
from a CairoSurface (then storing it in a DB) - that was already covered I think.
So, still not a really convincing example from your side, why one would need the PictureBox-to-CairoSurface-direction.
Olaf
Wonderful example. vbRichClient5.Cairo is amazing, it can be used to develop very complex and very advanced applications. I wonder if it's easy and simple enough to develop some simple applications.
I made a simple test program, but I don't know how to use vbRichClient5.Cairo drawings to replace the drawing functions of VB.PictureBox.
Last edited by dreammanor; Jan 9th, 2018 at 01:21 PM.