Sign in to follow this  
Followers 0
ishldgetoutmore

Help with automating MS Paint crop-n-save process

10 posts in this topic

I made a mistake this past week at the office. We've got a cable tester in the office, and the results are being saved as screenshots in PNG format. They asked me to manipulate the images a particular way. I completed the twenty or so they had there by hand. My algorithm was pretty simple, I thought:

1) Open file in MS Paint.

2) Copy a specific portion of the image, starting at 0,48 to 880,690.

3) Paste it as a new image.

4) Hit Cttl+I to invert the image colors.

5) Make a text box from 399,717 to 464,732 and put in the name of the file (without the extension) in Arial 10-point bold type.

6) Save the file with the same name as the original but in .JPG format.

7) Print the file to the CutePDF Writer I have installed, in black & white.

Sadly, because I was successful in this, they suddenly gave me several hundred files to manipulate. While I was willing to do it as a one-off, doing it to hundreds of files is tedious, labor-intensive, and (frankly) something of a waste of my time. Unfortunately for me, the people in the cable QC area are less computer-savvy than I, and for them this algorithm is apparently impossible to achive, despite the fact that I used programs that were already installed on all the computers. But the reward for doing work properly is more work.

So, I'm looking for a script that anyone can run, that takes all of the PNG files in a particular directory and does the above process on them. I remembered back from when I did some TeraTerm scripting (using LogMeTT) that a lot of the forum regulars there recommended AutoIt highly. Can AutoIt automate this process for me and save my fragile sanity?

Share this post


Link to post
Share on other sites

Hang on!

you went and brought more work on yourself, and now you want to burden your workmates with more work too.

tut tut :idea:

What? I thought that's how it worked in IT!?!

:)

It serves me right, really. The manager of that group is unsure of how to copy files to his USB stick.

Share this post


Link to post
Share on other sites

Check out the _GDIPlus_XXXXX stuff. You can actually do all of that with _GDIPlus alone, and all in the background.

I have to go to school in just a moment, but if nobody has given you an example before I get back, I will write a quick example for you.

Good luck.

Share this post


Link to post
Share on other sites

Thank you, sir! I'll have to check that out!

Share this post


Link to post
Share on other sites

I hope this will do what you are wanting. You will have to tweak it to meet your specifications, but should get you on the right track.

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

;Image Crop Settings
Global $ImageCropPosX = 0, $ImageCropPosY = 48, $ImageCropWidth = 880, $ImageCropHeight = 642

;Text Box Settings For Image AFTER Crop
Global $TextBoxWidth = 100, $TextBoxHeight = 17, $TextBoxPosX = 780, $TextBoxPosY = 625, $TextColor = 0xFFFFFFFF, $TextBGcolor = 0xFF000000, $TextFont = "Arial", $TextSize = 10, $TextStyle = 1;1 = Bold

;Directory To Search In
$Dir = @DesktopDir & '\GDItest'

$aSearch = _Search($Dir, '*.png', 0, False)
If Not IsArray($aSearch) Then
    MsgBox(0, "Ooops", 'No png files found in "' & $Dir & '"')
Else
    _GDIPlus_Startup()
    $hBrush = _GDIPlus_BrushCreateSolid($TextColor)
    $hBrush2 = _GDIPlus_BrushCreateSolid($TextBGcolor)
    $hFormat = _GDIPlus_StringFormatCreate()
    $hFamily = _GDIPlus_FontFamilyCreate($TextFont)
    $hFont = _GDIPlus_FontCreate($hFamily, $TextSize, $TextStyle)
    $tLayout = _GDIPlus_RectFCreate($TextBoxPosX, $TextBoxPosY, $TextBoxWidth, $TextBoxHeight)
    For $a = 1 To $aSearch[0]
        $SS = StringSplit($aSearch[$a], '\')
        $sNewName = StringReplace($SS[$SS[0]], '.png', '.jpg')
        If Not FileExists($Dir & '\' & $sNewName) Then
            $hImage1 = _GDIPlus_ImageLoadFromFile($aSearch[$a])
            $hClone = _GDIPlus_BitmapCloneArea($hImage1, $ImageCropPosX, $ImageCropPosY, $ImageCropWidth, $ImageCropHeight)
            $hGraphics1 = _GDIPlus_ImageGetGraphicsContext($hClone)
            _GDIPlus_GraphicsFillRect($hGraphics1, $TextBoxPosX, $TextBoxPosY + 1, $TextBoxWidth, $TextBoxHeight, $hBrush2)
            _GDIPlus_GraphicsDrawStringEx($hGraphics1, $sNewName, $hFont, $tLayout, $hFormat, $hBrush)
            _GDIPlus_ImageSaveToFile($hClone, $Dir & '\' & $sNewName)
        EndIf
    Next
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_BrushDispose($hBrush2)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_FontDispose($hFont)
    If IsDeclared('hGraphics1') Then _GDIPlus_GraphicsDispose($hGraphics1)
    If IsDeclared("hImage1") Then _GDIPlus_ImageDispose($hImage1)
    If IsDeclared("hClone") Then _WinAPI_DeleteObject($hClone)
    _GDIPlus_Shutdown()
EndIf

;### SEARCH FUNCTION ###
;Returns array containing full path of matched files, with [0] containing the count of returned elements.
;
;PARAMETERS:
;
;$path        = start location of search
;
;$filter      = expression to use for file matching (e.g. *.txt)
;
;$depth       = folder depth to limit search
;               Default set to -1
;
;               Values:
;                   0  -> current folder only
;                   n  -> search up to n folders deep
;                   -1 -> search in all subfolders
;
;$directories = set to true if directories are to be included in the search results
;               Default set to True
;
;$files       = set to true if files are to be included in the search results
;               Default set to True
;
;RETURN VALUE:
;
;Success:   Array of files and folders matching the search parameter.
;           [0] contains the count of matched elements.
;           matched folders end with "\"
;
;Failure:   Returns 0.
;           Sets @error to:
;               1   -> $path does not exist.
;               2   -> No matches found.
;
Func _Search($path, $filter = "*", $depth = -1, $directories = True, $files = True)
    ;check directory exists
    If FileExists($path) Then
        ;add "\" to end of path value if needed
        If StringCompare(StringRight($path, 1), "\") <> 0 Then
            $path &= "\"
        EndIf
        Local $result = ""
        ;conduct search
        _SearchUtil($result, $path, $filter, $depth, $directories, $files)
        ;create return array
        If StringCompare(StringRight($result, 1), "|") == 0 Then
            $result = StringTrimRight($result, 1)
            $result = StringSplit($result, "|")
        Else
            $result = 0
            SetError(2, 0, 0)
        EndIf
        Return $result
    Else
        SetError(1, 0, 0)
    EndIf
EndFunc   ;==>_Search
Func _SearchUtil(ByRef $result, $path, $filter, $depth, $directories, $files)
    Local $search = FileFindFirstFile($path & $filter)
    Local $fname
    If $search <> -1 Then
        While 1
            $fname = FileFindNextFile($search)
            If @error == 1 Then
                ExitLoop
            EndIf
            ;skip processing if directory/file is not included in search results
            If @extended == 1 Then
                If Not $directories Then
                    ContinueLoop
                Else
                    $fname &= "\"
                EndIf
            Else
                If Not $files Then
                    ContinueLoop
                EndIf
            EndIf
            ;add file to results
            $result &= $path & $fname & "|"
        WEnd
        FileClose($search)
    EndIf
    ;process subdirectories if within depth parameter
    If $depth <> 0 Then
        $search = FileFindFirstFile($path & "*")
        While 1
            $fname = FileFindNextFile($search)
            If @error == 1 Then
                ExitLoop
            EndIf
            ;search subdirectory
            If @extended == 1 Then
                _SearchUtil($result, $path & $fname & "\", $filter, $depth - 1, $directories, $files)
            EndIf
        WEnd
        FileClose($search)
    EndIf
EndFunc   ;==>_SearchUtil
;### END SEARCH FUNCTION ###

Share this post


Link to post
Share on other sites

Thank you so much! I was looking at the GDIPlus script yesterday with one of the other engineers in my department, and we were thrilled by the possibilities. We'll test this script but I am much more confident that AuoIt will prove useful for this and many other projects! The last time I looked at it, it was good; it may have achieved greatness while I wasn't paying attention.

I can feel the long-disused scripter part of my brain stirring to life! :idea:

Share this post


Link to post
Share on other sites

Oops... use this one instead... the other may leak memory a little since I had released the resources improperly from GDI... $hGraphics1, $hImage1, and $hClone should have been released in the For loop since there will be multiple files... the rest can still be released after the main loop since they are created once and used for every file.

Glad AutoIt could resurrect the scripter in you!

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

;Image Crop Settings
Global $ImageCropPosX = 0, $ImageCropPosY = 48, $ImageCropWidth = 880, $ImageCropHeight = 642

;Text Box Settings For Image AFTER Crop
Global $TextBoxWidth = 100, $TextBoxHeight = 17, $TextBoxPosX = 780, $TextBoxPosY = 625, $TextColor = 0xFFFFFFFF, $TextBGcolor = 0xFF000000, $TextFont = "Arial", $TextSize = 10, $TextStyle = 1;1 = Bold

;Directory To Search In
$Dir = @DesktopDir & '\GDItest'

$aSearch = _Search($Dir, '*.png', 0, False)
If Not IsArray($aSearch) Then
    MsgBox(0, "Ooops", 'No png files found in "' & $Dir & '"')
Else
    _GDIPlus_Startup()
    $hBrush = _GDIPlus_BrushCreateSolid($TextColor)
    $hBrush2 = _GDIPlus_BrushCreateSolid($TextBGcolor)
    $hFormat = _GDIPlus_StringFormatCreate()
    $hFamily = _GDIPlus_FontFamilyCreate($TextFont)
    $hFont = _GDIPlus_FontCreate($hFamily, $TextSize, $TextStyle)
    $tLayout = _GDIPlus_RectFCreate($TextBoxPosX, $TextBoxPosY, $TextBoxWidth, $TextBoxHeight)
    For $a = 1 To $aSearch[0]
        $SS = StringSplit($aSearch[$a], '\')
        $sNewName = StringReplace($SS[$SS[0]], '.png', '.jpg')
        If Not FileExists($Dir & '\' & $sNewName) Then
            $hImage1 = _GDIPlus_ImageLoadFromFile($aSearch[$a])
            $hClone = _GDIPlus_BitmapCloneArea($hImage1, $ImageCropPosX, $ImageCropPosY, $ImageCropWidth, $ImageCropHeight)
            $hGraphics1 = _GDIPlus_ImageGetGraphicsContext($hClone)
            _GDIPlus_GraphicsFillRect($hGraphics1, $TextBoxPosX, $TextBoxPosY + 1, $TextBoxWidth, $TextBoxHeight, $hBrush2)
            _GDIPlus_GraphicsDrawStringEx($hGraphics1, $sNewName, $hFont, $tLayout, $hFormat, $hBrush)
            _GDIPlus_ImageSaveToFile($hClone, $Dir & '\' & $sNewName)
            _GDIPlus_GraphicsDispose($hGraphics1)
            _GDIPlus_ImageDispose($hImage1)
            _WinAPI_DeleteObject($hClone)
        EndIf
    Next
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_BrushDispose($hBrush2)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_Shutdown()
EndIf

;### SEARCH FUNCTION ###
;Returns array containing full path of matched files, with [0] containing the count of returned elements.
;
;PARAMETERS:
;
;$path        = start location of search
;
;$filter      = expression to use for file matching (e.g. *.txt)
;
;$depth       = folder depth to limit search
;               Default set to -1
;
;               Values:
;                   0  -> current folder only
;                   n  -> search up to n folders deep
;                   -1 -> search in all subfolders
;
;$directories = set to true if directories are to be included in the search results
;               Default set to True
;
;$files       = set to true if files are to be included in the search results
;               Default set to True
;
;RETURN VALUE:
;
;Success:   Array of files and folders matching the search parameter.
;           [0] contains the count of matched elements.
;           matched folders end with "\"
;
;Failure:   Returns 0.
;           Sets @error to:
;               1   -> $path does not exist.
;               2   -> No matches found.
;
Func _Search($path, $filter = "*", $depth = -1, $directories = True, $files = True)
    ;check directory exists
    If FileExists($path) Then
        ;add "\" to end of path value if needed
        If StringCompare(StringRight($path, 1), "\") <> 0 Then
            $path &= "\"
        EndIf
        Local $result = ""
        ;conduct search
        _SearchUtil($result, $path, $filter, $depth, $directories, $files)
        ;create return array
        If StringCompare(StringRight($result, 1), "|") == 0 Then
            $result = StringTrimRight($result, 1)
            $result = StringSplit($result, "|")
        Else
            $result = 0
            SetError(2, 0, 0)
        EndIf
        Return $result
    Else
        SetError(1, 0, 0)
    EndIf
EndFunc   ;==>_Search
Func _SearchUtil(ByRef $result, $path, $filter, $depth, $directories, $files)
    Local $search = FileFindFirstFile($path & $filter)
    Local $fname
    If $search <> -1 Then
        While 1
            $fname = FileFindNextFile($search)
            If @error == 1 Then
                ExitLoop
            EndIf
            ;skip processing if directory/file is not included in search results
            If @extended == 1 Then
                If Not $directories Then
                    ContinueLoop
                Else
                    $fname &= "\"
                EndIf
            Else
                If Not $files Then
                    ContinueLoop
                EndIf
            EndIf
            ;add file to results
            $result &= $path & $fname & "|"
        WEnd
        FileClose($search)
    EndIf
    ;process subdirectories if within depth parameter
    If $depth <> 0 Then
        $search = FileFindFirstFile($path & "*")
        While 1
            $fname = FileFindNextFile($search)
            If @error == 1 Then
                ExitLoop
            EndIf
            ;search subdirectory
            If @extended == 1 Then
                _SearchUtil($result, $path & $fname & "\", $filter, $depth - 1, $directories, $files)
            EndIf
        WEnd
        FileClose($search)
    EndIf
EndFunc   ;==>_SearchUtil
;### END SEARCH FUNCTION ###

Share this post


Link to post
Share on other sites

Okay, I've been playing with this, and it's very nice code! Thanks to danwilli, I feel confident what I want can be done.

I then went through the forums and added on a bit to invert the final image.

However, I noticed something. Depending on the image I use, sometimes the inversion seems lose details from the image. It seems to happen predominantly to the right side of my image, but that could be due to the image in question. I'm wondering what the "best" way is to invert the colors in the JPG or PNG image. Any suggestions?

http://www.autoitscript.com/forum/index.php?s=&showtopic=77799&view=findpost&p=563657

http://www.autoitscript.com/forum/index.php?s=&showtopic=86951&view=findpost&p=623855

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

It HAS to be done in MS Paint? Why not resize in autoit itself. I've read a bit to fast :mellow:

Mayby this could help.

#include <GDIPlus.au3>

Local $fod = FileOpenDialog("", @DesktopDir, "All files (*.*)")
Local $fsd = FileSaveDialog("", @DesktopDir, "All files (*.*)")

_ResizeImage($fod, $fsd, 100, 100)

ShellExecute($fsd)

Func _ResizeImage($sFile, $sOutput, $iWidth, $iHeight)
    Local $hBMP, $hImage1, $hImage2, $hGraphic
    _GDIPlus_Startup()
    $hBMP = _WinAPI_CreateBitmap($iWidth, $iHeight, 1, 32)
    $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage1)
    $hImage2 = _GDIPlus_ImageLoadFromFile($sFile)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImage2, 0, 0, $iWidth, $iHeight)
    _GDIPlus_ImageSaveToFile($hImage1, $sOutput)

    _GDIPlus_ImageDispose($hImage1)
    _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteObject($hBMP)
    _GDIPlus_Shutdown()
EndFunc
Edited by AlmarM

Minesweeper

A minesweeper game created in autoit, source available.

_Mouse_UDF

An UDF for registering functions to mouse events, made in pure autoit.

2D Hitbox Editor

A 2D hitbox editor for quick creation of 2D sphere and rectangle hitboxes.

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