Dim ImgF As WIA.ImageFile
Dim ImgP As WIA.ImageProcess
Set ImgF = New WIA.ImageFile
ImgF.LoadFile "Zapotec.bmp"
Set ImgP = New WIA.ImageProcess
With ImgP
.Filters.Add .FilterInfos!Convert.FilterID
.Filters.Item(1).Properties!FormatID.Value = wiaFormatJPEG
.Filters.Item(1).Properties!Quality.Value = 70
Set ImgF = .Apply(ImgF)
End With
ImgF.SaveFile "Zapotec.jpg"
Quite more complex than dilettante's method but I have used this many times and it works
Form code
Code:
'
'
SaveJPG Picture1.Picture, App.Path & "\MyJpegPicture.jpg", 80 ' range is 0 to 100
'
'
Module code
Code:
Option Explicit
Public Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Public Type GdiplusStartupInput
GdiplusVersion As Long
DebugEventCallback As Long
SuppressBackgroundThread As Long
SuppressExternalCodecs As Long
End Type
Public Type EncoderParameter
GUID As GUID
NumberOfValues As Long
Type As Long
Value As Long
End Type
Public Type EncoderParameters
Count As Long
Parameter As EncoderParameter
End Type
Public Declare Function GdiplusStartup Lib "GDIPlus" _
(token As Long, _
inputbuf As GdiplusStartupInput, _
Optional ByVal outputbuf As Long = 0) As Long
Public Declare Function GdiplusShutdown Lib "GDIPlus" (ByVal token As Long) As Long
Public Declare Function GdipCreateBitmapFromHBITMAP Lib "GDIPlus" _
(ByVal hbm As Long, _
ByVal hPal As Long, _
Bitmap As Long) As Long
Public Declare Function GdipDisposeImage Lib "GDIPlus" (ByVal Image As Long) As Long
Public Declare Function GdipSaveImageToFile Lib "GDIPlus" _
(ByVal Image As Long, _
ByVal filename As Long, _
clsidEncoder As GUID, _
encoderParams As Any) As Long
Public Declare Function CLSIDFromString Lib "ole32" (ByVal str As Long, id As GUID) As Long
Public Sub SaveJPG(ByVal pict As StdPicture, ByVal filename As String, Optional ByVal quality As Long) '= 80
Dim tSI As GdiplusStartupInput
Dim lRes As Long
Dim lGDIP As Long
Dim lBitmap As Long
' Initialize GDI+
tSI.GdiplusVersion = 1
lRes = GdiplusStartup(lGDIP, tSI)
If lRes = 0 Then
' Create the GDI+ bitmap
' from the image handle
lRes = GdipCreateBitmapFromHBITMAP(pict.Handle, 0, lBitmap)
If lRes = 0 Then
Dim tJpgEncoder As GUID
Dim tParams As EncoderParameters
' Initialize the encoder GUID
CLSIDFromString StrPtr("{557CF401-1A04-11D3-9A73-0000F81EF32E}"), tJpgEncoder
' Initialize the encoder parameters
tParams.Count = 1
With tParams.Parameter ' Quality
' Set the Quality GUID
CLSIDFromString StrPtr("{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}"), .GUID
.NumberOfValues = 1
.Type = 4
.Value = VarPtr(quality)
End With
' Save the image
lRes = GdipSaveImageToFile(lBitmap, StrPtr(filename), tJpgEncoder, tParams)
' Destroy the bitmap
GdipDisposeImage lBitmap
End If
' Shutdown GDI+
GdiplusShutdown lGDIP
End If
If lRes Then
Err.Raise 5, , "Cannot save the image. GDI+ Error:" & lRes
End If
End Sub
Anything I post is an example only and is not intended to be the only solution, the total solution nor the final solution to your request nor do I claim that it is. If you find it useful then it is entirely up to you to make whatever changes necessary you feel are adequate for your purposes.
Do I need to call up a specific project reference or obtain a specific .dll?
Reference to Microsoft Windows Image Acquisition Library v2.0, built into modern Windows versions but can be downloaded and installed in XP SP1 or later.
Dilettante, Noted re. the WIA library requirement. However I will need the routine to run on Win98SE and 2000 machines too. Can your excellent simple method be made compatible with these too?
camoore
Wales
UK
Last edited by camoore; Jul 5th, 2012 at 10:29 AM.
Reason: typo
Sorry, when Microsoft created this to replace the older Kodak Imaging library Windows XP was the current version. There is a lot of "new" stuff that was never even back-ported to XP so I've been happy with this.
But there are 3rd party libraries you can buy, or else you can use GDI+ code like jmsrikland showed.
Hmm, come to think of it GDI+ requires WinXP as well doesn't it?
Last edited by dilettante; Jul 5th, 2012 at 10:05 AM.
It is, for me at least, a shame that the WIA Library is apparently not compatible with Win 98/2000 machines because Dilettante's code is so beautifully simple and elegant. Thank you very much for the suggestion, which I shall file for future use on machines running WinXP sp1 or later.
The GDI+ method kindly suggested by jmsrikland looks at first sight to be very complicated (and uses code with which I am not familiar at my level of VB6 knowledge). However its implementation is very straightford, with all the complicated stuff going into a module and just a simple 1-line of code to call it up from inside a form/program. The link from program to module is by calling up the Public subroutine "Save JPG".
Complicated though the code looks (to me!) I created a module, copied the code into it and hey presto it worked perfectly first time. So MANY thanks jmsrikland. This was a "perfect" answer to my problem. Now to study that module code and figure out how it works. I have found much reference to GDI+ by internet searches, but as yet no comprehensive description of what it is, how it works and what else it can achieve. It looks to be a very powerful graphical tool.
(Dilettante - that GDI+ method is working fine on a win98SE machine)
I will mark this thread as resolved, leave appropriate feedback to you helpful contributors and hope that the thread may in future prove of assistance to other members searching this forum.
camoore
Wales
UK
Last edited by camoore; Jul 5th, 2012 at 10:32 AM.
Reason: Add (afterthought) for Dilettante
GDI+ can be used in all Windows-based applications. GDI+ was introduced in Windows XP and Windows Server 2003. For information about which operating systems are required to use a particular class or method, see the More Information section of the documentation for the class or method. GDI+ is available as a redistributable for earlier operating systems.
There is also a caveat about rebasing the DLL.
From that it doesn't sound like Win98 (even SE) ships with GDI+, so maybe you got lucky and tested on a machine with some other software installed that deploys GDI+ there?
Last edited by dilettante; Jul 5th, 2012 at 11:39 AM.
Reason: typos
The docs are not well organized for use, probably because the flat API is not recommended or supported.
Windows GDI+ exposes a flat API that consists of about 600 functions, which are implemented in Gdiplus.dll and declared in Gdiplusflat.h. The functions in the GDI+ flat API are wrapped by a collection of about 40 C++ classes. It is recommended that you do not directly call the functions in the flat API. Whenever you make calls to GDI+, you should do so by calling the methods and functions provided by the C++ wrappers. Microsoft Product Support Services will not provide support for code that calls the flat API directly.
I have checked what is loaded to the Windows\System folder (where a 98SE machine keeps its .dll)
It has GDI.exe and GDI32.dll both dated 23/4/99 and GDIPlus.dll dated 29/8/02.
I have no idea whence these came - whether shipped with the original 98SE CD or imported through the installation of some program. The computer is pretty well stacked with programs, several of which have to do with photo image processing (eg.Microsoft Photodraw). The machine also had an "unofficial" 98SE sp2 update installed, which someone produced after MS ceased to support 98SE.
I produced an installation package for my program (using the VB6 P&D deployment wizard) and had it make a dependency file list. Included in this list was GDIPlus.dll - which as aforesaid was resident in my Windows\System folder. That .dll would presumably be essential for any machine to run the code supplied by jmsrikland.
(I would comment that for Win2000 onwards the .dll need to be in the Windows\System32 folder)
Thank you Dilettante for pointers to more info. about what GDI+ can do. I wish I could find a book on the subject which introduces it and all its many capabilities in plain simple English, with VB6 tutorials!
camoore
Wales
UK
Last edited by camoore; Jul 5th, 2012 at 12:26 PM.
Reason: typo
It looks like somebody goofed on that machine then. Here is what the REDIST.TXT says:
===========
Gdiplus.dll
===========
For Windows XP use the system-supplied gdiplus.dll. Do not install a new gdiplus.dll over the system-supplied version (it will fail due to Windows File Protection).
For Windows 2000, Windows Millennium Edition, Windows NT 4.0 and Windows 98, install gdiplus.dll into the private directory of the application not into the system directory.
In addition to the rights granted in Section 1 of the Agreement ("Agreement"), with respect to gdiplus.dll for Windows 2000, Windows Millennium Edition, Windows NT 4.0 and Windows 98, you have the following non-exclusive, royalty free rights subject to the Distribution Requirements detailed in Section 1 of the Agreement:
(1) You may distribute gdiplus.dll solely for use with Windows 2000, Windows Millennium Edition, Windows NT 4.0 and Windows 98.
I would not jump to the conclusion that you can just copy the XP version of this DLL to other systems either.
If you are using the PDW to create setups get the redist download from Microsoft, expand it, and copy the DLL to the PDW's REDIST folder.
Last edited by dilettante; Jul 5th, 2012 at 12:45 PM.
Ideally you would create a .DEP file to go with the .DLL that would instruct the PDW to install it into the app folder. But doing this on XP or later can lead to problems.
I guess the real fix is to use a more flexible installer technology that can conditionally install items based on the target OS.
Get rid of Win98 machines. They aren't even getting security patches so they're dangerous anyway. Even XP is mostly dead now.
Another approach I didn't mention was the old Intel JPEG library. But as far as I know you can only use this legally if you have a (at one time free) license for it, and Intel stopped issuing licenses long ago.
Excuse me for butting in dilettante but can WIA be used to save (say) a PictureBox straightout to a .jpg, instead of SavePicture to a .bmp and then convert.
Sadly, no. You need some outboard function to accomplish that. WIA 2.0 can create a StdPicture as output, but it cannot take one as input. Very frustrating oversight.
I've even tried that (extracting from a StdPicture to a byte array, then compressing the BMP bytes to JPEG using WIA) and it works, except... I can't get the graphics that were drawn on a PictureBox (.Line, .Print, etc.).
Simple demo attached. However to use it:
Requires a reference to Edanmo's OLE interfaces and functions typelib (olelib.tlb).
Last edited by dilettante; Jul 5th, 2012 at 02:54 PM.
Reason: added demo
Goofed or not, the jmsrikland code works fine on my 98SE machines relying, as far as I can tell, on their having GDIPlus.dll v.29/08/02 loaded to the Windows\System folder. As above mentioned, this .dll gets listed as a dependency file by the VB Studio P&D wizard.
I have yet to try the program on my XP machine (which is undergoing update). It will be interesting to see a. Whether that has a GDIPlus.dll loaded, b. What version it is and c. Whether the jmsrikland code works on my XP machine. My guess is that it will, but I will have to report that fact back to this thread later when the XP computer is up and running again. The XP machine has VB6 fully loaded, so this test will not be quite the same as were it to be a "clean install" of my program without the machine's having any VB6 history of loaded .dll etc. etc. I do not right now have access to an XP machine with no VB6 ever loaded/used thereon.
camoore
Wales
UK
If a P&D wizard produced deployment package is used, there should come up a warning if it tries to replace a later .dll with an earlier version. If that happened, I would of course opt to retain the later version.
Last edited by camoore; Jul 5th, 2012 at 03:16 PM.
My 98SE machines have, for whatever historical reason, got an early version of GDIPlus.dll in their windows\system folder, and the code from jmsrikland works "perfectly" as far as I can tell.
If/when it comes to try this program in a Win2000, XP, Vista or 7 machine, be assured we will not attempt to write into their system32 folders any GDIPlus.dll version which is other than that which they already contain - by virtue of its having come with their OS or, for whatever reason, having been downloaded/installed subsequently.
It remains to be seen whether the jmsrikland code works OK with later versions of GDIPlus.dll such as may have been distributed with the OS, or otherwise. If I hit problems, I will make further post(s) to this thread.
Magic Ink,
In no way are you butting in to this thread. These threads are for all users/members of whatever level of knowledge, and anyone having something to contribute and/or question and/or comment is surely VERY welcome to join in. As you will see from the above posts, Dilettante is very knowledgeable about this (and many other) topics. Whereas I started the thread, I do please invite you to continue to contribute to it and will read your further posts with interest.
The jmsrikland code allows a picture box content to be converted directly into a .jpg file without need for an intermediate .bmp to be generated as far as a user is concerned. However I have a suspicion that the code in the Module does in fact generate a bitmap file, uses it in the conversion and then deletes it - so it does not clog up memory space.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
there is also bmp2jpeg.dll which is free to use, if you can still find it
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Thanks. I see from the link you supplied that FREEIMAGE appears to be still currently supported - a recent update having been made March 2012 to fix some 64 bit issues.