Sign in to follow this  
Followers 0
careca

Extract .jpg from .mp3

13 posts in this topic

#1 ·  Posted (edited)

To extract the first jpg from an mp3.

#include <String.au3>
#include <GDIPlus.au3>

Opt("MustDeclareVars", 0)

Local $Mp3 = FileOpenDialog('Select .mp3', '', 'Audio file (*.mp3)', 3)
Local $NewFile = @ScriptDir&"\Output.jpg"
Local $ReadH, $StartStr

Extract()

Func Extract()
$File = FileOpen($Mp3, 16)
$Read = FileRead($File)
FileClose($File)
$ReadH = _HexToString($Read)
$StartStr = StringInStr($ReadH, 'image/jpeg', 2, 1)
$EndStr = StringInStr($ReadH, 'ÿÙ', 2, 1)
If $StartStr = 0 Then
    ConsoleWrite('No match for beginning of jpg!' &@CRLF)
Exit ;Exit because there is no image.
Else
If $EndStr = 0 Then
    ConsoleWrite('No match for end of jpg!' &@CRLF)
    ValidateIMG() ;So we search for more, found a beggining, there must be an end.
Else
$Diff = $EndStr+2 - $StartStr+13
$Mid = StringMid($ReadH, $StartStr+13, $Diff)
$StringFileHDL = FileOpen($NewFile, 18)
FileWrite($StringFileHDL, $Mid)
FileClose($StringFileHDL)
ValidateIMG()
EndIf
EndIf
EndFunc

Func ValidateIMG()
_GDIPlus_Startup()
$Load = _GDIPlus_ImageLoadFromFile($NewFile)
If $Load = 0 Then
    $i=1
    Do
    $i=$i+1
    ConsoleWrite('$i '& $i &@CRLF)
    $EndStr = StringInStr($ReadH, 'ÿÙ', 2, $i)
    $Diff = $EndStr+2 - $StartStr+13
$Mid = StringMid($ReadH, $StartStr+13, $Diff)
    $StringFileHDL = FileOpen($NewFile, 18)
FileWrite($StringFileHDL, $Mid)
FileClose($StringFileHDL)
    $Load = _GDIPlus_ImageLoadFromFile($NewFile)
    ConsoleWrite('$Load '& $Load &@CRLF)
    Until $Load <> 0 Or $i = 10
    If $i = 10 Then
        MsgBox(64, 'Error', 'Couldnt find end of jpg!')
    EndIf
EndIf
GDIPlus_Shutdown()
EndFunc

EDIT: Corrected as sugested by wakillon.

Edited by careca

Spoiler

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

Renamer - Rename files and folders, remove portions of text from the filename etc.

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Firefox Profile Backup - Backup/restore previously saved profile.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

 

Share this post


Link to post
Share on other sites



FileConstants.au3 is not needed but _GDIPlus_ShutDown yes

And i have tried with 3 dozen of mp3 without a jpg found...

Do i need to test with some special mp3 ?  :ermm:


AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Hi, thank you, i'll remove the include, and put GDIPlus_Shutdown() in.

No special mp3, just one that has at least one JPG in it.

PS: Managed to extract it in all the ones i tested, maybe yours got a png.

Do you see album art in players? Sometimes there are players that get the jpg that's in the same folder, and not the embedded one on the mp3.

Edited by careca

Spoiler

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

Renamer - Rename files and folders, remove portions of text from the filename etc.

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Firefox Profile Backup - Backup/restore previously saved profile.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

 

Share this post


Link to post
Share on other sites

With VLC sometimes it display a picture, but don't know if it's by downloading from a database or by extracting from my mp3.


AutoIt 3.3.14.2 X86 - SciTE 3.6.0WIN 8.1 X64 - Other Example Scripts

Share this post


Link to post
Share on other sites

You can verify if the image has a picture, with mp3tag.

Generaly speaking, if the script complains with: 'No match for beginning of jpg!'

It means it did not find the jpg header, so must likely, there's no picture.

Have you tried extracting with the ID3 udf?


Spoiler

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

Renamer - Rename files and folders, remove portions of text from the filename etc.

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Firefox Profile Backup - Backup/restore previously saved profile.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

 

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

@wakillon - not all mp3 files have embedded artwork. Sometimes there may just be no artwork at all, or an image file named the same as the mp3 file or something like folder.jpg will share the same parent folder. Personally I always embed, plus have the Folder.jpg as that allows for an album image, plus a different image per mp3 track if need be, and accommodates for many of the players out there.

EDIT

Sometimes people embed huge image files into mp3 files, quite unnecessarily. My rule of thumb by experience, is no larger than about 150 Kb's and 310 x 310 pixels. Some people embed front and back covers, and others embed full artwork from booklets as well. More and more players are now supporting the extra artwork, but I just stick to the front cover myself, but each to their own.

Edited by TheSaint

AutoIt.4.Life Clubrooms - Life is like a Donut (secret key)

Make sure brain is in gear before opening mouth!
Remember, what is not said, can be just as important as what is said.

Spoiler

What is the Secret Key? Life is like a Donut

If I put effort into communication, I expect you to read properly & fully, or just not comment.
Ignoring those who try to divert conversation with irrelevancies.
If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it.
I'm only big and bad, to those who have an over-active imagination.

I may have the Artistic Liesense ;) to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage)

userbar.png

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

You can load the JPG directly to your script without saving it to the disk first.

 

Example:

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>

Global $sFilename = FileOpenDialog("Select a file", "", "(*.*)")
If @error Then Exit MsgBox(16, "Error", "You must select a file", 10)
_GDIPlus_Startup()
Global $hBitmap = _GDIPlus_BitmapCreateFromJPGEmbeddedFile($sFilename)
If Not $hBitmap Then Exit MsgBox(16, "Error", "No JPG found in file", 10) * _GDIPlus_Shutdown()
Global Const $iW = _GDIPlus_ImageGetWidth($hBitmap), $iH = _GDIPlus_ImageGetHeight($hBitmap), $hGUI = GUICreate("Extracted JPG", $iW, $iH) * GUISetState()
Global Const $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
_GDIPlus_GraphicsDrawImageRect($hGfx, $hBitmap, 0, 0, $iW, $iH)

Do
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_GraphicsDispose($hGfx)
            _GDIPlus_BitmapDispose($hBitmap)
            _GDIPlus_Shutdown()
            GUIDelete()
            Exit
    EndSwitch
Until False


Func _GDIPlus_BitmapCreateFromJPGEmbeddedFile($sFile, $sFilename = "", $bSave = True, $iTries_max = 20) ;coded by UEZ build 2014-07-25 beta
    If Not FileExists($sFile) Then Return SetError(1, 0, 0)
    Local Const $iFileSize = FileGetSize($sFile)
    If $iFileSize > 50 * 1024^2 Then Return SetError(2, 0, 0) ;skip files larger than 50 MB
    Local $binFile = Binary(FileRead($sFile))
;~  $binFile = StringReplace($binFile, "FFD8FFE000104A464946", "FFD8FFE000104A464946")
;~  ConsoleWrite(@extended & @CRLF) ;amount of JPGs found -> multi extract not implemented yet
    Local Const $iPos_Header = StringInStr($binFile, "FFD8FFE000104A464946")
    If Not $iPos_Header Then Return SetError(3, 0, 0)
    Local $iPos_Start = $iPos_Header, $iPos_End = StringInStr($binFile, "FFD9", 0, 1, $iPos_Start + 21)
    If Not $iPos_End Then Return SetError(4, 0, 0)
    Local $binJPG, $iSize = $iPos_End - $iPos_Header + 4, $iTries = 0

    Do
        $binJPG = StringMid($binFile, $iPos_Header, $iSize)

        If StringLeft($binJPG, 20) = "FFD8FFE000104A464946" Then
            $binJPG = Mod(StringLen($binJPG), 2) ? Binary("0x" & $binJPG & "0") : Binary("0x" & $binJPG)
            $hBmp = _GDIPlus_BitmapCreateFromMemory($binJPG) ;test whether extracted binary string is a valid JPG image using GDI+ (not save!)
            If $hBmp Then ExitLoop
        EndIf
        $iPos_Start = $iPos_End + 5
        $iPos_End = StringInStr($binFile, "FFD9", 0, 1, $iPos_Start)
        $iSize = $iPos_End - $iPos_Header + 4
        $iTries += 1
    Until $iTries = $iTries_max; Or $iPos_Start > $iFileSize
    If $iTries = $iTries_max Or $iPos_Start > $iFileSize Then Return SetError(5, 0, 0)
    If $bSave And $sFilename <> "" Then
        Local Const $hFile = FileOpen($sFilename, 18)
        If @error Then Return SetError(6, 0, $hBmp)
        FileWrite($hFile, Binary($binJPG))
        FileClose($hFile)
    EndIf
    Return $hBmp
EndFunc

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Very nice! i'll look into it, it's a good alternative if you don't want the picture file itself. :)

Thank you


Spoiler

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

Renamer - Rename files and folders, remove portions of text from the filename etc.

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Firefox Profile Backup - Backup/restore previously saved profile.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

 

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Added save option - see post #7. Sure, it returns a bitmap handle although you want to save it only.

 

To do: extract multi JPG images from a file -> maybe add multi image format extraction like BMP, PNG, GIF.

 

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

It fails when/if there are any instances of "FFD9" before the end of the file,

that's why mine loops to a maximum of 10 instances, and verifies for the validity of each occurence.

If i add that to your script, it should work flawlessly.

Good work!

Edited by careca

Spoiler

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

Renamer - Rename files and folders, remove portions of text from the filename etc.

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Firefox Profile Backup - Backup/restore previously saved profile.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

 

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Ok, thanks. I found another problem where on some MP3 files: $binJPG = Binary("0x" & StringMid($binFile, $iPos_Header, $iPos_End - $iPos_Header + 4)) doesn't convert it to binary but converts the chars to hex!

E.g. instead of 0xFFD8FFE000104A4649 it converts the binary string to 0x307846464438464645 (converts each char to hex because it is interpreted as a string).

Edit:

Seems that the way I did doesn't work and the binary string is "corrupted" when there are more "FFD9" entries and the result is not modulo 2 = 0.

 

Should be fixed now and now it searches for the end of the JPG part -> post #7.

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

The method to find the end of a JPG file by testing it with GDI+ is not save!

Br,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Was laying around with your script, and did basically the same thing,

but in a different structure and without saving.

I find it more readable.

Goes like this:

#Region ;Wrapper
#AutoIt3Wrapper_UseX64=n
#AutoIt3Wrapper_Run_Tidy=y
#EndRegion ;Wrapper
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <FileConstants.au3>

Local $hBitmap, $binJPG, $ReadB, $StartStr, $EndStr, $StartStr
Local $Filename = @ScriptDir & '\01 Starships.mp3'
;Local $Filename = @ScriptDir & '\Can´T Stop This Thing We Started.mp3'
;Local $Filename = @ScriptDir & '\Auréa Be My Baby.Mp3'

Extract()

Func Extract()
    _GDIPlus_Startup()
    $FileO = FileOpen($Filename)
    $Read = FileRead($FileO)
    $ReadB = Binary($Read)
    FileClose($FileO)
    $StartStr = StringInStr($ReadB, "4A464946", 0, 1)
    ConsoleWrite('$StartStr ' & $StartStr & @CRLF)
    $EndStr = StringInStr($ReadB, "FFD9", 0, 1)
    ConsoleWrite('$EndStr ' & $EndStr & @CRLF)
    If $StartStr = 0 Then
        ConsoleWrite('No match for beginning of jpg!' & @CRLF)
        Exit ;Exit because there is no image.
    Else
        If $EndStr = 0 Then
            ConsoleWrite('No match for end of jpg!' & @CRLF)
            FindEnd() ;So we search for more, found a beggining, there must be an end.
        Else
            ValidateIMG()
        EndIf
    EndIf
EndFunc   ;==>Extract

Func FindEnd()
    $i = 1
    Do
        $i = $i + 1
        ConsoleWrite('$i ' & $i & @CRLF)
        $EndStr = StringInStr($ReadB, "FFD9", 0, $i)
        ConsoleWrite('$EndStr ' & $EndStr & @CRLF)
        $binJPG = Binary("0x" & StringMid($ReadB, $StartStr - 12, $EndStr + 4 - $StartStr + 12))
        $hBitmap = _GDIPlus_BitmapCreateFromMemory($binJPG)
        If $hBitmap <> 0 Then
            ShowImg()
        EndIf
    Until $hBitmap <> 0 Or $i = 10
    If $i = 10 Then
        MsgBox(64, 'Error', 'Couldnt find end of jpg!')
    EndIf
EndFunc   ;==>FindEnd

Func ValidateIMG()
    $binJPG = Binary("0x" & StringMid($ReadB, $StartStr - 12, $EndStr + 4 - $StartStr + 12))
    $hBitmap = _GDIPlus_BitmapCreateFromMemory($binJPG)
    If @error = 3 Then
        FindEnd()
    Else
        ShowImg()
    EndIf
EndFunc   ;==>ValidateIMG

Func ShowImg()
    Local $iW = _GDIPlus_ImageGetWidth($hBitmap)
    Local $iH = _GDIPlus_ImageGetHeight($hBitmap)
    Local $hGUI = GUICreate("Extracted JPG", $iW, $iH) * GUISetState()
    Local $hGfx = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    _GDIPlus_GraphicsDrawImageRect($hGfx, $hBitmap, 0, 0, $iW, $iH)
EndFunc

Do
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            _GDIPlus_GraphicsDispose($hGfx)
            _GDIPlus_BitmapDispose($hBitmap)
            _GDIPlus_Shutdown()
            GUIDelete()
            Exit
    EndSwitch
Until False

Also, it's very possible to retrieve all images, but i just don't care, and the script i first posted works for my needs, and it's quick enough

Feel free to add whatever.


Spoiler

Paster - Main function is to paste text, but has more functions.

OpenW - Open With... alternative, Open any file with any application, set it's icon, set application as default.

Renamer - Rename files and folders, remove portions of text from the filename etc.

BeatsPlayer - Music player.

Params Tool - Right click an exe to see it's parameters or execute them.

Regedit Control - Registry browsing history, quickly jump into any saved key.

Time4Shutdown - Write the time for shutdown in minutes.

Power Profiles Tool - Set a profile as active, delete, duplicate, export and import.

Firefox Profile Backup - Backup/restore previously saved profile.

Finished Task Shutdown - Shuts down pc when specified window/Wndl/process closes.

NetworkSpeedShutdown - Shuts down pc if download speed goes under "X" Kb/s.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0