Page 1 of 2

Convert BMP 2 JPEG without UseJPEGImageEncoder

Posted: Sat Aug 02, 2008 12:58 pm
by Wolf
Today when i use JPEGImageEncoder in my first graphic project see size of my exe increase about 40 KB :shock:

Why size of this librarie is so big? If exist another Userlibrary,dll, command line program or ..... to convert from bmp to jpeg with less size please presentation it.

Posted: Sat Aug 02, 2008 1:07 pm
by Sparkie
I myself haven't used it, but take a look at http://www.purebasic.fr/english/viewtop ... di+wrapper


(40kb = a drop in the bucket IMO.)

Posted: Sat Aug 02, 2008 1:56 pm
by srod

Code: Select all

#GDIPLUS_OK = 0

;-Structures.
  Structure GdiplusStartupInput ;{
    GdiPlusVersion.l 
    *DebugEventCallback.DebugEventProc
    SuppressBackgroundThread.l 
    SuppressExternalCodecs.l 
  EndStructure


;-Imports.
  Import "gdiplus.lib"
    GdiplusStartup(token, *input.GdiplusStartupInput, output) 
    GdiplusShutdown(token)
    GdipCreateBitmapFromFile(filename.p-unicode, *bitmap)
    GdipSaveImageToFile(image, filename.p-unicode, *clsidEncoder.CLSID, *encoderParams)
    GdipDisposeImage(image)
  EndImport


;First initialise gdi+.
  input.GdiplusStartupInput
  input\GdiPlusVersion = 1
  GdiplusStartup(@token, @input, #Null)
  ;Was the initialisation successful?
    If token
      If GdipCreateBitmapFromFile("test.bmp", @image) = #GDIPLUS_OK
        GdipSaveImageToFile(image, "test.jpg", ?clsid_jpeg, 0)
        GdipDisposeImage(image)
      EndIf
      ;Tidy up.
        GdiplusShutdown(token)
    EndIf

End

;CLSID for the gdi+ jpeg encoder.
DataSection
clsid_jpeg:
  Data.l $557CF401
  Data.w $1A04, $11D3
  Data.b $9A, $73, $00, $00, $F8, $1E, $F3, $2E
EndDataSection

Posted: Sat Aug 02, 2008 2:52 pm
by Sparkie
Nice one srod. 8)

Posted: Sat Aug 02, 2008 2:56 pm
by srod
Sparkie wrote:Nice one srod. 8)
t'was nothing really, -all I did was enumerate the encoder clsid's and use some old code I had for saving png's using gdi+. :)

@Wolf : note that gdi+ is only available on XP onwards. For a crossplatform solution there is the freeImage library -although bitmaps have to be converted to 24-bit first before attempting to save as a jpeg. This library is very good, but is somewhat larger than 40 kb! :wink:

Posted: Sat Aug 02, 2008 11:23 pm
by Wolf
Sparkie wrote:I myself haven't used it, but take a look at http://www.purebasic.fr/english/viewtop ... di+wrapper
Hi dear Sparkie, glad to see you :D

Thanks for the link :wink:

To: srod

Damn... size after compile = 3.50 KB :shock:

I'm confounded ..... :!: How does this working? i don't hear any about gdi+ until today, it's like API include in windows? or maybe i must put gdiplus.lib library always in project folder?

Anyway how can i change jpeg compression rate in this source?

And at end big thanks for this magical code.... shock again! :shock:

Posted: Sun Aug 03, 2008 10:57 am
by srod
Hi Wolf,

the gdi+ library comes pre-installed on XP, 2003 and Vista. For other systems you need to copy the gdi+redistributable etc.

As for jpeg compression; sorry, my knowledge of jpeg and gdi+ is 'functional' at best! :) I will take a real good look at gdi+ at some point.

Posted: Sun Aug 03, 2008 12:46 pm
by Wolf
Thanks srod, your knowledge do nice help for me :D

But it be really great if we can change jpeg compression in this method :!:

Posted: Sun Aug 03, 2008 1:26 pm
by PB
> gdi+ is only available on XP onwards

Not on all XP. When I run the code on XP Pro (SP3) I get this error:

Code: Select all

---------------------------
PureBasic - Linker error
---------------------------
POLINK: fatal error: File not found: 'gdiplus.lib'.
---------------------------
OK
---------------------------

Posted: Sun Aug 03, 2008 2:07 pm
by superadnim
But that means your PB installation doesn't have the library file so the linker can't do anything about your code... It doesn't mean the system doesn't have the DLL though, right?.

Posted: Sun Aug 03, 2008 2:09 pm
by PB
I don't know. It's not my code, so I don't know where the problem lies.

Posted: Sun Aug 03, 2008 2:10 pm
by srod
REMOVED

Posted: Sun Aug 03, 2008 2:21 pm
by srod
Here is the gdi+ code for saving a bitmap in jpeg format with a specified compression level (0 = max compression, 100 = least compression) :

Code: Select all

#GDIPLUS_OK = 0

  Enumeration
    #EncoderParameterValueTypeByte          = 1
    #EncoderParameterValueTypeASCII         = 2
    #EncoderParameterValueTypeShort         = 3
    #EncoderParameterValueTypeLong          = 4
    #EncoderParameterValueTypeRational      = 5
    #EncoderParameterValueTypeLongRange     = 6
    #EncoderParameterValueTypeUndefined     = 7
    #EncoderParameterValueTypeRationalRange = 8
    #EncoderParameterValueTypePointer       = 9
  EndEnumeration 

;-Structures.
  Structure GdiplusStartupInput
    GdiPlusVersion.l 
    *DebugEventCallback.DebugEventProc
    SuppressBackgroundThread.l 
    SuppressExternalCodecs.l 
  EndStructure

  ;The following two structures are used for setting encoder parameters (in our case the 'quality' parameter).
    Structure EncoderParameter
      guid.GUID
      NumberOfValues.l
      Type.l
      Value.l
    EndStructure

    Structure EncoderParameters
      Count.i
      Parameter.EncoderParameter[1]
    EndStructure

;-Imports.
  Import "gdiplus.lib"
    GdiplusStartup(token, *input.GdiplusStartupInput, output) 
    GdiplusShutdown(token)
    GdipCreateBitmapFromFile(filename.p-unicode, *bitmap)
    GdipSaveImageToFile(image, filename.p-unicode, *clsidEncoder.CLSID, *encoderParams)
    GdipDisposeImage(image)
  EndImport


;Returns #True if succesful.
Procedure.l GdipSaveImageToJpeg(sourceFile$, destinationFile$, compression.l=100) ;Compression = 0 for max compression, 100 for least.
  Protected result, token, image
  Protected input.GdiplusStartupInput, encParams.EncoderParameters
  ;First initialise gdi+.
    input\GdiPlusVersion = 1
    GdiplusStartup(@token, @input, #Null)
    ;Was the initialisation successful?
      If token
        If GdipCreateBitmapFromFile(sourceFile$, @image) = #GDIPLUS_OK
          ;Sort out the compression.
            With encParams
              \Count = 1
              CopyMemory(?clsid_EncoderQuality, @\Parameter[0]\guid, SizeOf(GUID))
              \Parameter[0]\Type = #EncoderParameterValueTypeLong
              \Parameter[0]\NumberOfValues = 1
              \Parameter[0]\Value = @compression
            EndWith
          If GdipSaveImageToFile(image, destinationFile$, ?clsid_jpeg, encParams) = #GDIPLUS_OK
            result = #True
          EndIf
          GdipDisposeImage(image)
        EndIf
        ;Tidy up.
          GdiplusShutdown(token)
      EndIf
  ProcedureReturn result
EndProcedure


DataSection
;CLSID for the gdi+ jpeg encoder.
  clsid_jpeg:
    Data.l $557CF401
    Data.w $1A04, $11D3
    Data.b $9A, $73, $00, $00, $F8, $1E, $F3, $2E
;CLSID for the relevant gdi+ encoder parameter.
  clsid_EncoderQuality:
    Data.l $1D5BE4B5
    Data.w $FA4A, $452D
    Data.b $9C, $DD, $5D, $B3, $51, $05, $E7, $EB
EndDataSection


;Test.
  Debug GdipSaveImageToJpeg("test.bmp", "test.jpg", 0) ;Compression = 0 for max compression, 100 for least.

@PB : your system will have the gdiplus.dll for sure. The import library is a different matter though - either you have it or you do not! :) I can upload one somewhere if you need?

Posted: Sun Aug 03, 2008 2:28 pm
by Sparkie
@PB: do a Windows search for gdiplus.lib. If found, place a copy in PureBasic\PureLibraries\Windows\Libraries\

Posted: Sun Aug 03, 2008 10:52 pm
by Wolf
To: srod
Work very well, thank you so much my friend :D

To: PB
Just go to Sparkie link at post number 2 and download:

http://home.comcast.net/~sfsxoi/gdiplus11_v3a.zip

After extract you see GdiPlus.lib in files just copy this file to folder of saved srod source, after compile and create exe you dont need more GdiPlus.lib in that folder.