bmp 2 jpg konvertieren

  • Hallo Community!

    Also ich suche einen schnellen weg um Bilddateien vom bmp nach jpg zu konvertieren... Ich spreche jetzt nicht von GDI Funktionen, sondern denke eher so an einer asm Funktion, oder eine fixe DLL / exe. Und es soll auch kein Irfanview oder so sein :wacko:

    Hat jemand vielleicht was parat oder ne Idee??

    Grüsse!

    P.S:
    Ich habe ja selber schon gegoogelt, und auch iwelche basic schnippsel gefunden; da war aber iwie nichts wirklich bei...

    Einmal editiert, zuletzt von Techmix (15. August 2011 um 16:21)

  • Meinste (fix)?!?!?
    Hmmm muß ich wohl testen. Ich habe hier mehrere 1,5MB große bmp´s und muß diese Konvertieren, habe eigenlich vor gehabt das AU3 in der Zeit was anderes machen kann.

    Nun ja, werds Abends mal testen!
    Grüsse!

    [EDIT]
    Ich hab da noch was in Erinnerung: die Prospeed.dll beinhaltet auch eine Prospeed_bpm2jpg.dll - die kann ich doch bestimmt iwie ansprechen...

    Einmal editiert, zuletzt von Techmix (14. August 2011 um 18:13)

  • Zitat

    GDI+ basiert auf eine DLL und das Umwandeln sollte auch mit GDI+ relativ fix gehen.


    Das dachte ich auch... Aber bei mir dauert die Funktion _GDIPlus_ImageSaveToFileEx alleine, je nach Größe des Bildes, bis zu einer Sekunde an.
    Das Problem ist, dass GDI+ eine komplett neue Datei abspeichert. Es könnte mit einer Funktion, die eine Datei direkt konvertiert, schneller gehen. Im englischen Forum lässt dich bestimmt etwas geeignetes finden.
    Allerdings gibt es auch das Problem, dass die Schreibgeschwindigkeit der Festplatte das ganze bei größeren Dateien ein wenig ausbremst. Wie sehr, kann ich nicht sagen.

  • name22:
    Genau das habe ich auch gedacht, also wegen der Dateigrösse... Die schreibgeschwindigkeit ist eher 2.Rangig. Ihr kennt doch bestimmt dieses 'Mona-Lisa' ASM Script von Seubo - an sowas dachte ich.

    misterspeed:
    Fremdprogramme muß ich leider vermeiden, ich hatte ja auch mit Irfanview eine Funktion...

  • misterspeed:
    Fremdprogramme muß ich leider vermeiden, ich hatte ja auch mit Irfanview eine Funktion...

    Wo liegt nun der Unterschied zwischen einer fremden exe, dieser prospeed.dll (die wohl keine windows standard dll sein dürfte) oder einem fremden ASM Code den du vermutlich nicht verstehst?
    Imagemagick liefert soweit ich weiss auch DLL's aus, sehe da aber nun keinen nennenswerten Vorteil zur enthaltenen convert.exe.

    Imagemagick ist sogar opensource: http://www.imagemagick.org/script/install-source.php#windows
    Quellcode zur convert.exe ist ebenfalls enthalten ;)

  • Hier eine Funktion, um Bilder in JPGs umzuwandeln

    Spoiler anzeigen
    [autoit]


    #include-once
    #include <GDIPlus.au3>

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ======================================================================================
    ; Name ..........: Convert2JPG()
    ; Description ...: Converts any image to a JPG file
    ; Syntax ........: Convert2JPG($inFile, $outFile[, $scaleW = 1[, $scaleH = 1[, $jpgQuality = 90[, $interpolationMode = 7]]]])
    ; Parameters ....: $inFile - input file name - should be any image file except jpg
    ; $outFile - output filename
    ; $scaleW - [optional] any number from 0 to x to scale width factor. Default = 1 - no scale (default:1)
    ; $scaleH - [optional] (default:1)
    ; $jpgQuality - [optional] jpg quality settings: 0 - 100 whereas 100 is best quality (default:90)
    ; $interpolationMode - [optional] any number from 0-7 (default:7):
    ; 0 - Default interpolation mode
    ; 1 - Low-quality mode
    ; 2 - High-quality mode
    ; 3 - Bilinear interpolation. No prefiltering is done
    ; 4 - Bicubic interpolation. No prefiltering is done
    ; 5 - Nearest-neighbor interpolation
    ; 6 - High-quality, bilinear interpolation. Prefiltering is performed to ensure high-quality shrinking
    ; 7 - High-quality, bicubic interpolation. Prefiltering is performed to ensure high-quality shrinking
    ; Return values .: Success -> True
    ; Failure:
    ; 1 - either no input or output file is given
    ; 2 - scale factor width or height is incorrect
    ; 3 - jpg quality value is out of range (0-100)
    ; 4 - interpolation mode value is out of range (0-7)
    ; 5 - $scaleW or $scaleH or $jpgQuality or $interpolationMode values are not numbers
    ; 6 - bitmap could not be created
    ; 7 - scaled bitmap could not be created
    ; 8 - scaled bitmap could not be saved
    ; 9 - bitmap could not be created
    ; Author ........: UEZ 2011
    ; Version .......: v0.90 build 2011-08-14
    ; Modified ......:
    ; Remarks .......:
    ; Related .......: GDIPlus.au3
    ; =================================================================================================
    Func Convert2JPG($inFile, $outFile, $scaleW = 1, $scaleH = 1, $jpgQuality = 90, $interpolationMode = 7)
    If $inFile = "" Or $outFile = "" Then Return SetError(1, 0, 0)
    If $scaleW < 0 Or $scaleH < 0 Then Return SetError(2, 0, 0)
    If $jpgQuality < 0 Or $jpgQuality > 100 Then Return SetError(3, 0, 0)
    If $interpolationMode < 0 Or $interpolationMode > 7 Then Return SetError(4, 0, 0)
    If Not IsNumber($scaleW) Or Not IsNumber($scaleH) Or Not IsNumber($jpgQuality) Or Not IsNumber($interpolationMode) Then Return SetError(5, 0, 0)
    Local $declared = True
    If Not $ghGDIPDll Then
    _GDIPlus_Startup()
    $declared = False
    EndIf
    If StringRight($outFile, 4) <> ".jpg" Then $outFile &= ".jpg"
    Local Const $sCLSID = _GDIPlus_EncodersGetCLSID("JPG")
    Local $tParams = _GDIPlus_ParamInit(1)
    Local $tData = DllStructCreate("int Quality")
    DllStructSetData($tData, "Quality", $jpgQuality)
    Local $pData = DllStructGetPtr($tData)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
    Local Const $pParams = DllStructGetPtr($tParams)
    Local Const $hBitmap = _GDIPlus_BitmapCreateFromFile($inFile)
    If Not $hBitmap Then Return SetError(6, 0, 0)
    Local $iW = _GDIPlus_ImageGetWidth($hBitmap)
    Local $iH = _GDIPlus_ImageGetHeight($hBitmap)
    Local $save, $err = 0
    If $scaleW <> 1 Or $scaleH <> 1 Then
    Local Const $newW = $iW * $scaleW
    Local Const $newH = $iH * $scaleH
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateBitmapFromScan0", "int", $newW, "int", $newH, "int", 0, "int", 0x0026200A, "ptr", 0, "int*", 0)
    If @error Then Return SetError(7, 0, 0)
    Local $hBmp_scaled = $aResult[6]
    Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBmp_scaled)
    DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "handle", $hContext, "int", $interpolationMode)
    _GDIPlus_GraphicsDrawImageRect($hContext, $hBitmap, 0, 0, $newW, $newH)
    _GDIPlus_GraphicsDispose($hContext)
    $save = _GDIPlus_ImageSaveToFileEx($hBmp_scaled, $outFile, $sCLSID, $pParams)
    $tParams = 0
    $tData = 0
    If Not $save Then $err = 8
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_BitmapDispose($hBmp_scaled)
    If Not $declared Then _GDIPlus_Shutdown()
    If $err Then Return SetError($err, 0, 0)
    Return True
    EndIf
    $save = _GDIPlus_ImageSaveToFileEx($hBitmap, $outFile, $sCLSID, $pParams)
    $tParams = 0
    $tData = 0
    If Not $save Then $err = 9
    _GDIPlus_BitmapDispose($hBitmap)
    If Not $declared Then _GDIPlus_Shutdown()
    If $err Then Return SetError($err, 0, 0)
    Return True
    EndFunc

    [/autoit]

    Falls ihr Fehler findet, bitte melden!

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Da es um die Geschwindigkeit geht, würde ich das so machen:

    Spoiler anzeigen
    [autoit]

    #include <File.au3>
    #include <GDIPlus.au3>
    #include <GDIPlusConstants.au3>
    #include <WinAPI.au3>

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup()

    [/autoit] [autoit][/autoit] [autoit]

    Global $tGUID = _WinAPI_GUIDFromString("{557CF401-1A04-11D3-9A73-0000F81EF32E}")
    Global $pGUID = DllStructGetPtr($tGUID)

    [/autoit] [autoit][/autoit] [autoit]

    Global $tParams = _GDIPlus_ParamInit(1)
    Global $pParams = DllStructGetPtr($tParams)
    Global $tData = DllStructCreate("int Quality")
    DllStructSetData($tData, "Quality", 50)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, DllStructGetPtr($tData))

    [/autoit] [autoit][/autoit] [autoit]

    Global $aFiles = _FileListToArray(@ScriptDir & "\BMP\", "*.bmp")
    Global $iTimer = TimerInit()
    For $i = 1 To $aFiles[0]
    _ConvertBMP2JPG(@ScriptDir & "\BMP\" & $aFiles[$i])
    Next
    ConsoleWrite(TimerDiff($iTimer) & @CRLF)
    _GDIPlus_Shutdown()

    [/autoit] [autoit][/autoit] [autoit]

    Func _ConvertBMP2JPG($sFileName)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipLoadImageFromFile", "wstr", $sFileName, "ptr*", 0)
    DllCall($ghGDIPDll, "int", "GdipSaveImageToFile", "handle", $aResult[2], "wstr", StringTrimRight($sFileName, 3) & "jpg", "ptr", $pGUID, "ptr", $pParams)
    DllCall($ghGDIPDll, "int", "GdipDisposeImage", "handle", $aResult[2])
    EndFunc ;==>_ConvertBMP2JPG

    [/autoit]

    Diese Variante ist fast genauso schnell wie FreeImage.dll und mehr als doppelt so schnell wie Convert.exe (ImageMagic)
    Das sollte doch ausreichen, oder ;)

    Edit: Falls du FreeImage testen willst, das wäre die Funktion dafür:

    [autoit]

    Func _ConvertBMP2JPG_FreeImage($sFileName)
    Local $aResult = DllCall($hDll, "ptr", "_FreeImage_Load@12", "int", 0, "str", $sFileName, "int", 0)
    DllCall($hDll,"int", "_FreeImage_Save@16", "int", 2, "ptr", $aResult[0], "str", StringTrimRight($sFileName,3) & "jpg", "int", 50)
    DllCall($hDll, "none", "_FreeImage_Unload@4", "ptr", $aResult[0])
    EndFunc

    [/autoit]
  • Also ich habe jetzt die Funktion von eukalypus eingebaut, diese braucht auf meinem ollen P4-1600 für 100 bmp´s 7.71 sek mit der freeimage brauchte er sogar 7.89 sek.

    Also Danke nochmals an alle!
    Grüsse!

  • Hier die Ergebnisse meines Vergleichs:

    Code
    ImageMagick: 9683.29187089421
    GDIPlus: 7424.86768569748
    UEZ: 8915.10261779081
    FreeImage: 6704.62195614247
    FreeImage New: 7547.15529487686

    Um Convert.exe eine Chance zu geben, hab ich immer 10 Instanzen gleichzeitig gestartet, was die Konvertierung etwas beschleunigt hat - ist aber immer noch an letzter Stelle.

    bei "FreeImage" handelt es sich um die Version 3.9.3, welche ich seit etwa 4 Jahren benutze

    "FreeImage New" ist die nahezu aktuelle Version 3.15.0 aus Prog@ndy´s UDF: http://progandy.de/downloads/view.download/7

    evtl. kann man davon ausgehen, daß eine noch ältere Version von FreeImage.dll noch schneller und kleiner ist...

    E

  • eukalyptus: danke für den Benchmark! Wenn ich meine Funktion auf Speed optimieren würde, würde im Prinzip deine Version herauskommen!

    Die Unterschiede sind auch nicht so gravierend ausgefallen...

    Code
    Tool		ms		Speed
    FreeImage	6704,621956	100%
    GDIPlus		7424,867686	90,30%
    FreeImage New	7547,155295	88,84%
    UEZ		8915,102618	75,21%
    ImageMagick	9683,291871	69,24%


    Danke,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    2 Mal editiert, zuletzt von UEZ (15. August 2011 um 11:15)

  • Hmm nice. Könnt ihr vielleicht mal eure Benchscripte inklusive der benötigten DLLs noch zusammenfassend posten? Ist mit allen Varianten auch ein Verkleinern der Bildauflösung möglich?

  • Mit Ausnahme von meiner Lösung kann man mit allen auch die Größe des Bildes ändern

    Bei Convert.exe gibt man die gewünschte Größe einfach mit " size 320x240 " an
    Bei FreeImage sollte die Funktion so aussehen:

    [autoit]

    Func _ConvertBMP2JPG_FreeImage($sFileName)
    Local $aResult = DllCall($hDll, "ptr", "_FreeImage_Load@12", "int", 0, "str", $sFileName, "int", 0)
    Local $hDIB = $aResult[0]
    $aResult = DllCall($hDll, "ptr", "_FreeImage_Rescale@16", "ptr", $hDIB, "int", $iRescaleX, "int", $iRescaleY, "dword", 5)
    DllCall($hDll, "int", "_FreeImage_Save@16", "int", 2, "ptr", $aResult[0], "str", StringTrimRight($sFileName, 3) & "jpg", "int", 50)
    DllCall($hDll, "none", "_FreeImage_Unload@4", "ptr", $aResult[0])
    DllCall($hDll, "none", "_FreeImage_Unload@4", "ptr", $hDIB)
    EndFunc ;==>_ConvertBMP2JPG_FreeImage

    [/autoit]

    Und die Funktion von UEZ hat sowieso schon die entsprechenden Parameter eingebaut.

    Hier mein Benchmarkscript: autoit.de/wcf/attachment/13945/

    E