LarsJ

Navigating in an image

17 posts in this topic

#1 ·  Posted (edited)

Three main features are implemented to navigate in an image:

  • Zoom in/out with the mouse wheel
  • Click a point to zoom in/out around this point
  • Drag the image with the mouse to move it in the picture control
To zoom in/out the mouse pointer must be located over the picture control.

10 zoom levels are defined with the following zoom factors: 1, 2, 3, 4, 6, 8, 12, 16, 24, 32. A zoom factor of e.g. 24 means, that a pixel in the source image is shown as a 24x24 square in the picture control.

When you drag the image with the mouse and then zoom in/out, you'll zoom in/out around the point in the middle of the picture control.

The picture shows the GUI and an image of a small forest. The image is zoomed in to zoom factor 3. A pixel in the source image is shown as a 3x3 square in the picture control.

image1_zps81634e53.png

To zoom in/out around one of the two lakes, just click in the middle of the lake and zoom in/out, or drag the lake to the middle of the picture control and zoom in/out.

Keyboard actions

  • Page Up/Down to zoom in/out
  • Arrow keys to move the image a pixel at a time
  • Shift plus arrow keys to move the image a page at a time
To use the keyboard, the mouse pointer must be located over the picture control.

Menu bar

The menu bar is not implemented in this version.

Tab control

The purpose of the tab control is to be able to switch between more images. If you click a tab item, the image in the picture control will be replaced with the image in the tab item.

When you switch from one image to another, the image settings are stored and restored.

You can change the order of the images by dragging the tab items to the right or left.

Right (secondary) click a tab item to get a context menu for the image. Among other things, you can choose colors for the frame and grid (see below) that best fits respectively a bright and dark image. By default colors are set to fit a bright image.

Toolbars

image2_zps9ec7dc84.png

The left group is the File toolbar.

  • 1) New image
  • 2) Open image
  • 3) Save image
  • 4) Close image
The right group is the View toolbar.
  • 5) View mode
  • 6) Center middle point
  • 7) Frame is on/off
  • 8) Grid is on/off
Button 1, 3 and 5 are not implemented in this version.

You can right (secondary) click button 6, 7, and 8.

Note that all toolbar buttons are provided with tooltips.

More details

File toolbar

  • 2) Open image

    You can open multiple images at once.

    An image can be opened several times.

View toolbar
  • 5) View mode

    In this version there is only one mode: View mode. The button is always shown in pressed state. Except for that, there is not implemented any functionality for this button.

  • 6) Center middle point

    When you click the button, the middle of the source image will be positioned at the middle of the picture control. Zoom in/out will be around the middle point. This is the default when you open a new image.

    Right (secondary) click to center the corners (zoom in/out around the corners) of the source image.

  • 7) Frame is on/off

    If Frame is on and the image is smaller than the picture control, a frame is drawn around the image. This is especially useful for transparent images.

    Right (secondary) click to set the color of the frame.

  • 8) Grid is on/off

    If Grid is on, a grid is drawn for the five highest zoom factors (8, 12, 16, 24, 32). If the grid is drawn, the frame is not drawn.

    Right (secondary) click to set the color of the grid. Grid and frame are always set to the same color and drawn with the same color.

Status bar

The status bar is not used in this version.

Resize GUI

The initial size of the picture control is 6 * 96 pixels for both width and height. 96 is the smallest number that can be divided by all 10 zoom factors (1, 2, 3, 4, 6, 8, 12, 16, 24, 32) without giving a residue. This means, that there is always space for a whole number of pixels in the picture control. This makes all calculations much simpler. E.g. when the image is zoomed in/out, when the image is moved and when the grid is drawn.

The GUI and the picture control are resized in steps of 96 pixels. When the picture control is resized, the number of pixels is always increased or decreased with a whole number.

Transparent images

For a transparent image that really contains transparent pixels, it's necessary to clear the image control each time it's updated. This provides some flicker, especially when the image is moved.

For a non-transparent image, it's enough to clear the picture control when the image is zoomed out, and the image is smaller than the picture control. This makes navigation to work much smoother.

GIF- and PNG-images support transparency. This doesn't necessarily mean, that the images contain any transparent pixels. To verify that there are transparent pixels, you have to investigate every single pixel, and calculate if it's transparent or not. The investigation can stop, when you find the first transparent pixel, or at the end of the image. This can be time consuming. It's not done in this version.

Because of the issue with the flicker, a GIF- or PNG-image is by default set to be non-transparent.

If you open a GIF- or PNG-image you have to verify visually, if there are any transparent pixels. If this is the case, then right (secondary) click the tab item, and set the Transparent flag.

Merlin.gif and Torus.png (from the AutoIt installation), which are included as test images, does contain transparent pixels. For these images, the Transparent flag is set in the inifile. You can turn off the flag, to see what happens, if it's not set.

There is an issue with transparent images. If the picture control only contains pixels, that exactly matches the transparent color, which is set in pixel 0x0 in the source image, the picture control gets black.

Settings

In this version it's not possible to set and save settings. E.g. a setting to open an image automatically, when the program starts up. The five images that opens automatically, are typed directly into the inifile.

This version

This version is implemented for use in Non-rectangular selections in an image. Only functionality, that's needed in this example, is coded.

The code is not cleaned up according to double defined local variables or unused parameters in function calls (primary functions to handle windows messages). This means a lot of warnings if you run Au3Check.

Zipfile

The top level is the folder "Image Editor". It contains two subfolders: "1) Navigating in an image" and images. images is five test images. "1) Navigating in an image" contains source and resource files:

  • Navigating.au3 - run this script
  • includesVariables.au3 - common global variables
  • includesNavigatingImage.au3 - contains most of the calculations
  • includesDrawFunctions.au3 - draw image and graphics on top of image
  • includesTabCtrlFunctions.au3 - functions for the tab control
  • includesToolbarFunctions.au3 - functions for the toolbar
  • includestoolsFileToolbar.au3 - code for buttons in File toolbar
  • includestoolsViewToolbar.au3 - code for buttons in View toolbar
  • includesModernMenuRaw.au3 - copied from this thread by Holger
  • icons - icon files
Tested with AutoIt 3.3.10 on Windows 7 32/64 bit and Windows XP 32 bit.

Navigating.7z

Edited by LarsJ
2 people like this

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

An interesting start.
I will follow the development.
 
mLipok
 
EDIT:
I really like the zoom function.
Edited by mLipok

Signature beginning:   Wondering who uses AutoIT and what it can be used for ?
* GHAPI UDF - modest begining - comunication with GitHub REST API *
ADO.au3 UDF     POP3.au3 UDF     XML.au3 UDF    How to use IE.au3  UDF with  AutoIt v3.3.14.x  for other useful stuff click the following button

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API *

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 - BETA * ADO.au3 UDF SMTP Mailer UDF *

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Best coding practices * 

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * 

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2017-06-04

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

I download and check before you edit OP

edit:

so I had 9 minutes :)

Edited by mLipok

Signature beginning:   Wondering who uses AutoIT and what it can be used for ?
* GHAPI UDF - modest begining - comunication with GitHub REST API *
ADO.au3 UDF     POP3.au3 UDF     XML.au3 UDF    How to use IE.au3  UDF with  AutoIt v3.3.14.x  for other useful stuff click the following button

Spoiler

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. 

My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API *

My contribution to others projects or UDF based on  others projects: * _sql.au3 UDF  * POP3.au3 UDF *  RTF Printer - UDF * XML.au3 - BETA * ADO.au3 UDF SMTP Mailer UDF *

Useful links: * Forum Rules * Forum etiquette *  Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * 

Wiki: Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Best coding practices * 

IE Related:  * How to use IE.au3  UDF with  AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * 

I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions *  EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *

"Homo sum; humani nil a me alienum puto" - Publius Terentius Afer
"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming"
:naughty:  :ranting:, be  :) and       \\//_.

Anticipating Errors :  "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty."

Signature last update: 2017-06-04

Share this post


Link to post
Share on other sites

I can only repeat what I wrote in your other related post.

 

Man, this is impressive. I'm gobsmacked! :blink:

Thanks for sharing, etc. :D


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

You can add a feature to add a checkerboard background for transparent images to see if the image has transparency.

Well done!  :thumbsup:

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

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

Sure.
 
NavigatingImage.au3:

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <WinAPIvkeysConstants.au3>
#include <GuiStatusBar.au3>
#include <GDIPlus.au3>
;#include <Array.au3>

Opt( "MustDeclareVars", 1 )
Opt( "WinWaitDelay", 10 )

Global Const $sIniFile = "inifile\Navigating.ini"

Global $iImageCols = 23, $iImages = 0
Global $aImages[100][$iImageCols] ; Reg.exp. find: $aImages\[.*\]\[1\]
    ;
    ; Tab index is used as index in $aImages
    ;
    ; Columns:
    ;
    ;       0: Full name              ; Constant
    ;       1: State
    ;            Bit 0 =  1: New      ; + check overwrite    + check close
    ;            Bit 1 =  2: Paste    ; + check overwrite    + check close
    ;            Bit 2 =  4: Opened   ; - check overwrite
    ;            Bit 3 =  8: Modified ;                      + check close
    ;            Bit 4 = 16: Saved    ; - check overwrite
    ;            Bit 5 = 32: PosSize  ; Execute ImagePosSize()
    ;       2: Width                  ; Constant
    ;       3: Height                 ; Constant
    ;       4: Bitmap                 ; Constant ; Dispose
    ;       5: Context                ; Constant ; Dispose
    ;       6: $aColors
    ;       7: Not used
    ;       8: Zoom factor
    ;  9 - 12: $iXDest, $iYDest, $iWidthDest, $iHeightDest
    ; 13 - 16: $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc
    ; 17 - 18: $iXMiddleSrc, $iYMiddleSrc
    ; 19 - 20: $dxMax, $dyMax
    ;      21: Frame/grid
    ;      22: $fGraphics
    ;

;$aColors
    ; Columns:
    ; 0: For color, Back color, Frame/grid, Dark image, Not used
    ; 5: Transparent image (contains transparent pixels)

; Main windows, controls, handles
Global $hGui, $idTab, $hTab, $iTab = 0, $iTabPrev = 0, $iTabHeight, $idTabCtrl, $hPicChild, $idPicture, $hPicture, $hStatus

; Image and graphics variables
Global $hBitmap, $hContext, $hGraObj, $hBmpBuf, $hGraphics, $hDC, $hSrcDC
Global $hBitmap_Checkerboard, $hBrush_Checkerboard1, $hBrush_Checkerboard2, $hTexture_Checkerboard, $hContext_Checkerboard, _
            $iSize_Checkerboard = 32, $iColor1_Checkboard = 0xFFFFFFFF, $iColor2_Checkboard = 0xFFF4F4F4

; Control program flow
Global $fHandleEvents = 0
    ;   4: Toolbar button clicked
    ;  64: Drag tab item with primary mouse button
    ; 128: Move image with primary mouse button
    ; 256: Resize GUI and image

Global $fXP = ( @OSVersion = "WIN_XP" )

; Project includes
#include "includes\Variables.au3"
#include "includes\ModernMenuRaw.au3"
#include "includes\NavigatingImage.au3"
#include "includes\ToolbarFunctions.au3"
#include "includes\TabCtrlFunctions.au3"
#include "includes\DrawFunctions.au3"

ImageAndPixelEditor()


Func ImageAndPixelEditor()

    ; --- Create GUI ---

    ; Main GUI                                   (Menu->20; Toolbar->51; Tab->10,32; Status->28)
    $hGui = GUICreate( "Navigating in an image", $iPicWidth+10+51, $iPicHeight+20+32+28, 500, 50, _
                       BitXOR( BitOR( $WS_OVERLAPPEDWINDOW, $WS_CLIPCHILDREN ), $WS_MAXIMIZEBOX ) )
    GUIRegisterMsg( $WM_NCACTIVATE, "WM_NCACTIVATE" )
    GUISetState()

    ; Main menu
    Local $idFileMenu = GUICtrlCreateMenu( "File" )
    Local $idFileExit = _GUICtrlCreateODMenuItem( "Exit", $idFileMenu, "icons\exit.ico", 0 )
    ; New, Open (en fil kan åbnes flere gange), Reload

    ; Toolbar
    ToolbarCreate()

    ; Tab control
    TabCtrlCreate()

    ; Statusbar
    $hStatus = _GUICtrlStatusBar_Create( $hGui )
    _GUICtrlStatusBar_SetMinHeight( $hStatus, 24 )

    ; GUI width and height
    Local $aPos = WinGetPos( $hGui )
    $iWinWidth = $aPos[2]
    $iWinHeight = $aPos[3]
    $iMinWidth = $iWinWidth
    $iMinHeight = $iWinHeight

    ; Windows messages
    GUIRegisterMsg( $WM_ACTIVATE,      "WM_ACTIVATE"      )
    GUIRegisterMsg( $WM_MOUSEWHEEL,    "WM_MOUSEWHEEL"    )
    GUIRegisterMsg( $WM_GETMINMAXINFO, "WM_GETMINMAXINFO" )
    GUIRegisterMsg( $WM_SIZING,        "WM_SIZING"        )

    ; Catch key presses
    Local $hMessageHandler = DllCallbackRegister( "MessageHandler", "long", "int;wparam;lparam" )
    Local $hMessageHook = _WinAPI_SetWindowsHookEx( $WH_GETMESSAGE, DllCallbackGetPtr( $hMessageHandler ), 0, _WinAPI_GetCurrentThreadId() )

    ; --- Load first image ---

    ; Start GDIPlus
    _GDIPlus_Startup()

    ; Read inifile
    Local $sImageDir = StringLeft( @ScriptDir, StringInStr( @ScriptDir, "\", 0, -1 ) - 1 ) & "\images"
    Local $aPics = IniReadSection( $sIniFile, "Open on startup" ), $sImage, $fTrans, $hImage, $fOpen = False, $iNext
    If Not @error Then
        For $i = 1 To $aPics[0][0] Step 2
            If $aPics[$i][0] = "Image" And $aPics[$i+1][0] = "Transparent" Then
                $sImage = $sImageDir & "\" & $aPics[$i][1]
                $fTrans = $aPics[$i+1][1] = "1" ? True : False
                If $sImage <> $sImageDir And FileExists( $sImage ) Then
                    $iNext = $i + 2
                    $fOpen = True
                    ExitLoop
                EndIf
            EndIf
        Next
    EndIf

    If $fOpen Then
        ; Open on startup
        Local $i = StringInStr( $sImage, "\", 0, -1 )
        Local $sName = StringRight( $sImage, StringLen( $sImage ) - $i )
        _GUICtrlTab_SetItemText( $hTab, $iTab, $sName )
        $hImage = _GDIPlus_BitmapCreateFromFile( $sImage )
        $iImageWidth = _GDIPlus_ImageGetWidth( $hImage )
        $iImageHeight = _GDIPlus_ImageGetHeight( $hImage )
        $fTransparent = $fTrans ; Transparent?
        $aImages[0][1] = 4 ; State: Opened
    Else
        ; Default image
        $sImage = "New1.bmp"
        $iImageWidth = 256
        $iImageHeight = 256
        $aImages[0][1] = 3 ; State: New + Paste = default image
    EndIf

    ;checkerboard
    $hBitmap_Checkerboard = _GDIPlus_BitmapCreateFromScan0($iSize_Checkerboard, $iSize_Checkerboard)
    $hContext_Checkerboard = _GDIPlus_ImageGetGraphicsContext($hBitmap_Checkerboard)
    $hBrush_Checkerboard1 =  _GDIPlus_BrushCreateSolid($iColor1_Checkboard)
    $hBrush_Checkerboard2 =  _GDIPlus_BrushCreateSolid($iColor2_Checkboard)
    _GDIPlus_GraphicsFillRect($hContext_Checkerboard, 0, 0, $iSize_Checkerboard, $iSize_Checkerboard, $hBrush_Checkerboard1)
    _GDIPlus_GraphicsFillRect($hContext_Checkerboard, $iSize_Checkerboard / 2, 0, $iSize_Checkerboard / 2, $iSize_Checkerboard / 2, $hBrush_Checkerboard2)
    _GDIPlus_GraphicsFillRect($hContext_Checkerboard, 0, $iSize_Checkerboard / 2, $iSize_Checkerboard / 2, $iSize_Checkerboard / 2, $hBrush_Checkerboard2)
    $hTexture_Checkerboard = _GDIPlus_TextureCreate($hBitmap_Checkerboard)
    _GDIPlus_GraphicsDispose($hContext_Checkerboard)
    _GDIPlus_BrushDispose($hBrush_Checkerboard1)
    _GDIPlus_BrushDispose($hBrush_Checkerboard2)

    ; Image
    $hBitmap = _GDIPlus_BitmapCreateFromScan0( $iImageWidth, $iImageHeight )
    $hContext = _GDIPlus_ImageGetGraphicsContext( $hBitmap )
    If $fOpen Then
        _GDIPlus_GraphicsDrawImageRect( $hContext, $hImage, 0, 0, $iImageWidth, $iImageHeight )
        _GDIPlus_ImageDispose( $hImage )
    Else
        _GDIPlus_GraphicsClear( $hContext, 0xFFFFFFFF )
    EndIf

    ; Device contexts
    $hDC = _WinAPI_GetDC( $hPicture )
    $hSrcDC = _WinAPI_CreateCompatibleDC( $hDC )

    ; Image info
    $aImages[0][0] = $sImage       ; Full name
    $aImages[0][2] = $iImageWidth  ; Width
    $aImages[0][3] = $iImageHeight ; Height
    $aImages[0][4] = $hBitmap      ; Bitmap
    $aImages[0][5] = $hContext     ; Context
    $iImages += 1

    ; --- Draw graphics on top of the picture control using buffered drawing ---

    ; Create pen to draw frame and grid
    $hPenFrameGrid = _GDIPlus_PenCreate( 0xFFCCCCCC, 1 )
    ; Graphics object to draw the contents of the bitmap buffer on top of the picture control
    $hGraObj = _GDIPlus_GraphicsCreateFromHWND( $hPicture )
    ; Bitmap buffer for buffered graphics drawing
    $hBmpBuf = _GDIPlus_BitmapCreateFromGraphics( $iPicWidth, $iPicHeight, $hGraObj )
    ; Graphics context to draw graphics in the bitmap buffer
    $hGraphics = _GDIPlus_ImageGetGraphicsContext( $hBmpBuf )

    ; Positions and sizes
    ImagePosSize()

    ; Draw image
    ImageDraw( True )

    ; Open more pictures from inifile, if any
    If $fOpen Then
        For $i = $iNext To $aPics[0][0] Step 2
            If $aPics[$i][0] = "Image" And $aPics[$i+1][0] = "Transparent" Then
                $sImage = $sImageDir & "\" & $aPics[$i][1]
                $fTrans = $aPics[$i+1][1] = "1" ? True : False
                If $sImage <> $sImageDir And FileExists( $sImage ) Then _
                    OpenImageAdd( $sImageDir, $aPics[$i][1], $iImages, $fTrans )
            EndIf
        Next
    EndIf

    ; Remove focus from tab control
    GUICtrlSetState( $idLblForColor, $GUI_FOCUS )

    ; --- GUI main loop ---

    Local $iMsg, $aInfo, $fTabContextMenu = False
    While 1

        $iMsg = GUIGetMsg()
        ;ShowMessageCodesGUI( $iMsg, $sIdentifier = "", $iMaxInSeq = 0, $bOnlyOnce = False )
        ;ShowMessageCodesGUI( $iMsg, "GUI msg:", 2 )

        If $fHandleEvents Then

            Select
                Case BitAND( $fHandleEvents, 4 )   ; Toolbar button clicked
                    Switch $iMsg                     ; Switch statement is used for grouping of buttons
                        Case $idTbFileButton, $idTbViewButton
                            ToolbarButtonClick( $iMsg )
                    EndSwitch

                Case BitAND( $fHandleEvents, 64 )  ; Drag tab item with primary mouse button
                    DragTabItem()

                Case BitAND( $fHandleEvents, 128 ) ; Move image with primary mouse button
                    ImageMove( $aInfo[0], $aInfo[1] )

                Case BitAND( $fHandleEvents, 256 ) ; Resize GUI and image
                    ImageResize()
            EndSelect

        Else

            ; --- View mode ---

            Switch $iMsg

                Case $GUI_EVENT_MOUSEMOVE, 0
                    ContinueLoop

                Case $idTab, $idTabCtrl
                    $iTab = GUICtrlRead( $idTab )
                    If $iTabPrev <> $iTab Then ImageSwitch()
                    GUICtrlSetState( $idLblForColor, $GUI_FOCUS )
                    If $fTabContextMenu Then
                        $fTabContextMenu = False
                        TabContextMenu()
                    EndIf

                Case $GUI_EVENT_PRIMARYDOWN
                    $aInfo = GUIGetCursorInfo( $hPicChild )
                    If $aInfo[4] = $idPicture Then
                        ; - Click a point in picture control to center the point (zoom in/out around this point)
                        ; - Click and drag with the mouse to move the image in the picture control
                        $fHandleEvents = BitOR( $fHandleEvents, 128 )
                    Else
                        $aInfo = GUIGetCursorInfo( $hGui )
                        If $aInfo[4] = $idTab Then
                            ; Click on a tab item or right to tab items
                            If $iImages > 1 Then
                                Local $aPos = _GUICtrlTab_GetItemRect( $hTab, $iTab )
                                If $aInfo[0] - 51 > $aPos[0] And $aInfo[0] - 51 < $aPos[2] And $aInfo[1] < $iTabHeight Then _
                                    $fHandleEvents = BitOR( $fHandleEvents, 64 )
                            EndIf
                            GUICtrlSetState( $idLblForColor, $GUI_FOCUS )
                        ElseIf $aInfo[1] < 0 Then
                            ; Click in menu bar or title bar areas
                            GUICtrlSetState( $idLblForColor, $GUI_FOCUS )
                        EndIf
                    EndIf

                Case $GUI_EVENT_SECONDARYDOWN
                    If GUIGetCursorInfo( $hGui )[4] = $idTab Then
                        $aInfo = GUIGetCursorInfo( $hGui )
                        If $aInfo[0] > 51 And $aInfo[1] < $iTabHeight Then
                            Local $i = _GUICtrlTab_HitTest( $hTab, $aInfo[0] - 51, $aInfo[1] )[0]
                            If $i = -1 Then continueLoop
                            ; Right click on a tab item
                            If $i = $iTab Then
                                TabContextMenu()
                            Else
                                $fTabContextMenu = True
                                _GUICtrlTab_ClickTab( $hTab, $i )
                            EndIf
                        EndIf
                    EndIf

                Case $GUI_EVENT_RESTORE
                    ImageDraw()

                Case $GUI_EVENT_CLOSE, $idFileExit
                    ExitLoop

            EndSwitch

        EndIf

    WEnd

    ;_GDIPlus_ImageSaveToFile( $hBitmap, "images\Saved.bmp" )

    _WinAPI_UnhookWindowsHookEx( $hMessageHook )

    _GDIPlus_PenDispose( $hPenFrameGrid )

    For $i = 0 To $iImages - 1
        ReleaseImageResources( $i )
    Next

    ;_GDIPlus_BitmapDispose( $hBitmap )
    _GDIPlus_BitmapDispose( $hBmpBuf )
    ;_GDIPlus_GraphicsDispose( $hContext )
    _GDIPlus_GraphicsDispose( $hGraObj )
    _GDIPlus_GraphicsDispose( $hGraphics )
    _GDIPlus_BrushDispose($hTexture_Checkerboard)
    _WinAPI_ReleaseDC( $hPicture, $hDC )
    _WinAPI_DeleteDC( $hSrcDC )
    _GDIPlus_Shutdown()

    DestroyToolbars()
    GUIDelete( $hGui )
    Exit

EndFunc

ToolbarFunctions.au3:

#include-once

; --- File toolbar ---

; --- File | Open ---

Func OpenImages()
    ; Disable main GUI functionality
    GUISetState( @SW_DISABLE, $hGui ) ; Main GUI
    GUIRegisterMsg( $WM_NOTIFY, "" )  ; Toolbar events
    $fMoveZoom = False                ; Move/zoom

    Local $sWorkingDir = @WorkingDir
    Local $sProjectDir = StringLeft( @ScriptDir, StringInStr( @ScriptDir, "\", 0, -1 ) - 1 )
    Local $sOpen = FileOpenDialog( "Open one or more images", _
                                   $sProjectDir & "\images\", _
                                   "Images (*.bmp;*.gif;*.jpg;*.png)", _
                                   $FD_FILEMUSTEXIST + $FD_PATHMUSTEXIST + $FD_MULTISELECT, _
                                   "", $hGui )
    If Not @error Then
        ; Tab item for first image
        Local $iTabs = $iImages
        ;Local $iTabs = _GUICtrlTab_GetItemCount( $hTab )

        If StringInStr( $sOpen, "|" ) Then
            ; Multiple images
            Local $aOpen = StringSplit( $sOpen, "|" )
            Local $sDir = $aOpen[1]
            For $i = 2 To $aOpen[0]
                OpenImageAdd( $sDir, $aOpen[$i], $iTabs+$i-2 )
            Next
        Else
            ; Single images
            Local $i = StringInStr( $sOpen, "\", 0, -1 )
            Local $sFile = StringRight( $sOpen, StringLen( $sOpen ) - $i )
            Local $sDir = StringLeft( $sOpen, $i - 1 )
            OpenImageAdd( $sDir, $sFile, $iTabs )
        EndIf

        ; Switch tab to first Open image
        _GUICtrlTab_ClickTab( $hTab, $iTabs )
        $iTab = GUICtrlRead( $idTab )
        ImageSwitch( True ) ; True => Remove focus
    EndIf

    ; Enable main GUI functionality
    FileChangeDir( $sWorkingDir )                 ; Directory
    GUISetState( @SW_ENABLE, $hGui )              ; Main GUI
    GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" )     ; Toolbar events
    $fMoveZoom = True                             ; Move/zoom
    While GUIGetMsg() ; No (mouse) events from FileOpenDialog
    WEnd              ; should be passed on to main message loop.
EndFunc

Func OpenImageAdd( $sDir, $sFile, $iTab, $fTrans = False )
    ;ConsoleWrite( $sDir & "\" & $sFile & @CRLF )
    Local $sName = $sDir & "\" & $sFile

    ; Image info, bitmap, context
    Local $hImage = _GDIPlus_BitmapCreateFromFile( $sName )
    Local $iImageWidth = _GDIPlus_ImageGetWidth( $hImage )
    Local $iImageHeight = _GDIPlus_ImageGetHeight( $hImage )
    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0( $iImageWidth, $iImageHeight )
    Local $hContext = _GDIPlus_ImageGetGraphicsContext( $hBitmap )
    _GDIPlus_GraphicsFillRect($hContext, 0, 0, $iImageWidth, $iImageHeight, $hTexture_Checkerboard)
    _GDIPlus_GraphicsDrawImageRect( $hContext, $hImage, 0, 0, $iImageWidth, $iImageHeight )
    _GDIPlus_ImageDispose( $hImage )

    ; Store image info
    Local $aColors[6] = [ 0xFF000000, 0xFFFFFFFF, 1, _ ; For, back, frame/grid colors
                          0, 0, $fTrans ]              ; Dark image, not used, transparent image
    $aImages[$iImages][ 0] = $sName        ; Full name
    $aImages[$iImages][ 1] = 36            ; State: Opened + PosSize
    $aImages[$iImages][ 2] = $iImageWidth  ; Width
    $aImages[$iImages][ 3] = $iImageHeight ; Height
    $aImages[$iImages][ 4] = $hBitmap      ; Bitmap
    $aImages[$iImages][ 5] = $hContext     ; Context
    $aImages[$iImages][ 6] = $aColors      ; Colors
    $aImages[$iImages][ 8] = 1             ; Zoom level
    $aImages[$iImages][17] = -1            ; $iXMiddleSrc
    $aImages[$iImages][18] = -1            ; $iYMiddleSrc
    $aImages[$iImages][21] = 3             ; Frame/grid
    $aImages[$iImages][22] = 11            ; $fGraphics
    $iImages += 1

    ; Create tab item
    _GUICtrlTab_InsertItem( $hTab, $iTab, $sFile )
EndFunc

; --- File | Close ---

Func CloseImage()
    ; Only one image?
    If $iImages = 1 Then
        ; If this is default image (state 3 indicates default), then don't close it
        If BitAND( $aImages[0][1], 3 ) = 3 Then Return

        ; Not default image: Close image and create new default image

        ; Close image
        ;_GDIPlus_BitmapDispose( $hBitmap )
        ;_GDIPlus_GraphicsDispose( $hContext )

        ; Create new default image
        $iImageWidth = 256
        $iImageHeight = 256
        $hBitmap = _GDIPlus_BitmapCreateFromScan0( $iImageWidth, $iImageHeight )
        $hContext = _GDIPlus_ImageGetGraphicsContext( $hBitmap )
        _GDIPlus_GraphicsClear( $hContext, 0xFFFFFFFF )

        ; Store image info
        Local $aColors[6] = [ 0xFF000000, 0xFFFFFFFF, 1, _ ; For, back, frame/grid colors
                              0, 0, False ]                ; Dark image, not used, transparent image
        $aImages[0][ 0] = "New1.bmp"    ; Full name
        $aImages[0][ 1] = 3             ; State: New + Paste ; New + Paste = default image
        $aImages[0][ 2] = $iImageWidth  ; Width
        $aImages[0][ 3] = $iImageHeight ; Height
        $aImages[0][ 4] = $hBitmap      ; Bitmap
        $aImages[0][ 5] = $hContext     ; Context
        $aImages[0][ 6] = $aColors      ; Colors
        $aImages[0][ 8] = 1             ; Zoom level
        $aImages[0][21] = 3             ; Frame/grid
        $aImages[0][22] = 11            ; $fGraphics

        ; Update tab
        _GUICtrlTab_SetItemText( $hTab, $iTab, "New1.bmp" )
        $iTabPrev = $iTab

        ; Update image
        LoadImageInfo( $iTab )              ; Load info for this image
        ImagePosSize()                      ; Calculate image position and size
        $fGraphics = BitOR( $fGraphics, 4 ) ; Update grid in bitmap buffer
        ImageDraw( True )                   ; Draw image and grid
        ;Local $sColor = "0x" & Hex( $iCurBackColor, 6 )
        ;GUICtrlSetBkColor( $idLblBackColor, $sColor )
        Return
    EndIf

    $iTabPrev = -1
    ;_GDIPlus_BitmapDispose( $hBitmap )
    ;_GDIPlus_GraphicsDispose( $hContext )
    ReleaseImageResources( $iTab )
    _GUICtrlTab_DeleteItem( $hTab, $iTab )
    If $iTab = $iImages - 1 Then
        $iTab -= 1
    Else
        For $i = $iTab To $iImages - 2
            For $j = 0 To $iImageCols - 1
                $aImages[$i][$j] = $aImages[$i+1][$j]
            Next
        Next
    EndIf
    $iImages -= 1
    _GUICtrlTab_ClickTab( $hTab, $iTab )
EndFunc

; --- File | Save ---
Edited by UEZ
1 person likes this

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

Brilliant. Thank you. I feared that I had to use ImageMagick or similar.

I can see you have created a texture. When a new image is opened, the bitmap is filled out with the texture, and the image is drawn on top of the texture.

This seems to solve several issues: It's not necessary to erase the picture control every time the image is redrawn. The checkerboard overwrites the non-transparent pixels. This means that moving the image with the mouse is working much smoother with much lesser flicker.

The issue with a black picture when the picture control only contains completely transparent pixels seems olso to be fixed. The checkerboard is shown instead of the black picture.

When a selection is copy/pasted (Non-rectangular selections in an image), it can be pasted on top a checkerboard background instead of a white/red/green background.

It seems as if I have to update both examples.

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Thanks for the code, but please, can you make a lot easier version of this for the beginners. Maybe a file open dialog, where you can choose a picture and than, when the image is shown in the gui, only the possibility to zoom with the mouse wheel and to drag the image. Without the tabs, the toolbar, the menu etc.

I try to understand it and to make it useable for my own project, but it's hard for me. 

Edited by makeasy

Share this post


Link to post
Share on other sites

I'll make a version with a smaller amount of code. You'll probably have to wait for the weekend.

Share this post


Link to post
Share on other sites

Great. I will wait and try to solve some other problems :)

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Here is a version without the menu, toolbar, tab control and status bar. You can zoom image, move image and resize GUI. images\Image.bmp is opened on startup.

Add a new post if you have more questions.

Regards Lars.

Navigating.7z

Edited by LarsJ
1 person likes this

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

I got a cold this weekend and cant look deeper at the code. But my interest moved me out of the bed.  Here are my first impressions.

You met my wish and now  I should be able to use it for my project. Thanks a lot for your help!

There's a little bit strange behaviour. But this can be observed also in the bigger version and it's no problem for me: Its when you load heavier images, suchlike from a digicam. If you drag it ,for example, from left to right and drop it at the end position and then move your cursor fast back to the left, the image moves also a little bit to the left, although it was dropped. But I thinks thats only a problem on slower pc's, like my celeron laptop.

One question: If i load a bigger image from didigcam, i cant zoom out so far, that I see the whole image. Can you explain, how to adjust the zoom levels. 

I'm writing on a front end for imagemagick, with the possibility to insert variables in the imagemagick code. For earch var a configurable sliders appears and the changes of the image can be seen directly in the gui. If you are interested, I could tell you, when I present a first version.  Thanks again.

 

Edited by makeasy

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

I have not been able to reproduce this behaviour. I have tested with a 1600x1200 pixels bmp image. You can do some tests with the ImageMove function in the middle of NavigatingImage.au3. I tend to believe that the problem is related to AutoIt as an interpreted language. As all interpreted languages, it's a little bit slow at loops compared to compiled languages. You see it clearly if you move the image quickly back and forth several times without releasing the mouse. The picture has trouble keeping up with the mouse.

The zoom problem was easy. I have updated the zoom function to include 5 more levels: 1/8, 1/6, 1/4, 1/3 and 1/2. The new zoom function is much better than the old one. At some time I'll update the original code. I have just made a quick test. A few issues can not be excluded.

I would like to hear about your imagemagick front end. Is this something you are coding in AutoIt?

Navigating.7z

Edited by LarsJ

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

Just saw your new zoom function. Very good. 

Yes, the front end is coded in Autoit. There is the possibility to insert imagemagick commands in an edit field. There you can insert the variables. If you change a slider the variable is replaced with the slider value. A batch file will be created and the image will be processed with imagemagick. Maybe in a month I have a first version. Thanks for your interest.

Edited by makeasy

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