Jump to content

GDIPlus, Images, and some unusual behavior


Recommended Posts

I have a script where I take an image and rotate that 90 or 180 degrees. I am having some issues with the image rotated 180 degrees. Here is (a portion) of the script I am using:

_GDIPlus_Startup()

$hImage1 = _GDIPlus_ImageLoadFromFile(@ScriptDir&'\PNGs\'&$sName&'.png')
$hGraphic1 = _GDIPlus_ImageGetGraphicsContext($hImage1)
$hImage2 = _GDIPlus_BitmapCreateFromGraphics($nW,$nH,$hGraphic1)
$hGraphic2 = _GDIPlus_ImageGetGraphicsContext($hImage2)

$matrix = _GDIPlus_MatrixCreate()
_GDIPlus_MatrixRotate($matrix, $nAngle)
_GDIPlus_GraphicsSetTransform($hGraphic2, $matrix)
_GDIPlus_GraphicsDrawImage($hGraphic2, $hImage1, $nXOffset+$nRotOffsetX, $nYOffset+$nRotOffsetY)
_GDIPlus_ImageSaveToFile($hImage2,@ScriptDir&'\test.bmp')

_GDIPlus_MatrixDispose($matrix)
_GDIPlus_GraphicsDispose($hGraphic1)
_GDIPlus_GraphicsDispose($hGraphic2)
_GDIPlus_ImageDispose($hImage1)
_GDIPlus_ImageDispose($hImage2)
_GDIPlus_Shutdown()

The image width in this case is 52 and the heigth is 98. The $nXOffset adn $nYOffset are negative width and heigth, in this instance ($nAngle=180 degree rotation). The $nRotOffSetY is 1 and the $nRotOffSetX is either 0 or 1, but neither work. XOffset1x3.jpg shows the image dump (@300%) when the RotOffsetX is equal to one. It is hard to see, but on the left side of the image there is a black line of missing pixels. Okay, so the offset should be zero. XOffset0x3.jpg shows the image dump (@300%) when RotOffsetX is zero. In this image, you can see that the black line has shifted to the other side. It appears as if the image has become one pixel narrower when rotated 180 degrees. The 90 degree rotation of the image works fine (RotOffsetX=0,RotOffsetY=1) - it comes out to be a 98 by 52 image, edge to edge. (Start1.png shows the original file that is subject to rotation.)

The issue I have is that I am applying the images to a control and conecting a bunch together. With the change in size, they all become misaligned and the end result doesn't look as good as when the images are prerotated.

I don't know if I am missing something in the functions, if this is a bug, or a limitation of the way this script works. Any help would be greatly appreciated. Thanks!

post-34148-12638498368491_thumb.png

post-34148-12638503027337_thumb.jpg

post-34148-12638503150313_thumb.jpg

You can't see a rainbow without first experiencing the rain.

Link to comment
Share on other sites

Can you post a script which we could try? (Even if we need to use our own png.)

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

Download the "start1.png" attachment in the first post and place it in the script directory:

#include-once
#include <WinAPI.au3>
#include <GDIPlus.au3>
$nX=52
$nY=98

$hMain=GUICreate("Rotate Test",350,250,0,0)
GUISetBkColor(0x000000)
$hLabel=GUICtrlCreateLabel("",10,10,$nX,$nY)
GUICtrlSetBkColor(-1,0xFF00FF)
$hPicture=GUICtrlCreatePic("",10,10,$nX,$nY)

_GDIPlus_Startup()
$hImage1 = _GDIPlus_ImageLoadFromFile(@ScriptDir&'\start1.png')
$hBMP1=_GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage1)
_WinAPI_DeleteObject(GUICtrlSendMsg($hPicture, 0x0172, 0, $hBMP1))
_GDIPlus_ImageDispose($hImage1)

$hOriginal = GUICtrlCreateButton("Original",200,10,80,30)
$h90 = GUICtrlCreateButton("90 Rotation",200,50,80,30)
$h180_0=GUICtrlCreateButton("180 Rotation, 0",200,90,80,30)
$h180_1=GUICtrlCreateButton("180 Rotation, 1",200,130,80,30)

GUISetState(@SW_SHOW,$hMain)
While 1
    $nMsg=GUIGetMsg()
    Switch $nMsg
        Case -3
            Exit
        Case $hOriginal
            $nX=52
            $nY=98
            GUICtrlDelete($hPicture)
            GUICtrlDelete($hLabel)
            $hLabel=GUICtrlCreateLabel("",10,10,$nX,$nY)
            GUICtrlSetBkColor(-1,0xFF00FF)
            $hPicture=GUICtrlCreatePic("",10,10,$nX,$nY)
            $hImage1 = _GDIPlus_ImageLoadFromFile(@ScriptDir&'\start1.png')
            $hBMP1=_GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage1)
            _WinAPI_DeleteObject(GUICtrlSendMsg($hPicture, 0x0172, 0, $hBMP1))
            _GDIPlus_ImageDispose($hImage1)
        Case $h90
            $nX=98
            $nY=52
            $nAngle=90
            $nRotOffsetX=0
            $nRotOffsetY=1
            $nXOffset=0
            $nYOffset=-$nX
            _Rotate($nX,$nY,$nAngle,$nRotOffsetX,$nRotOffsetY,$nXOffset,$nYOffset)
        Case $h180_0
            $nX=52
            $nY=98
            $nAngle=180
            $nRotOffsetX=0
            $nRotOffsetY=1
            $nXOffset=-$nX
            $nYOffset=-$nY
            _Rotate($nX,$nY,$nAngle,$nRotOffsetX,$nRotOffsetY,$nXOffset,$nYOffset)
        Case $h180_1
            $nX=52
            $nY=98
            $nAngle=180
            $nRotOffsetX=1
            $nRotOffsetY=1
            $nXOffset=-$nX
            $nYOffset=-$nY
            _Rotate($nX,$nY,$nAngle,$nRotOffsetX,$nRotOffsetY,$nXOffset,$nYOffset)
    EndSwitch
WEnd

GUIDelete($hMain)
_GDIPlus_Shutdown()

Func _Rotate($nW,$nH,$nAngle,$nRotOffsetX,$nRotOffsetY,$nXOffset,$nYOffset)
    GUICtrlDelete($hPicture)
    GUICtrlDelete($hLabel)
    
    $hLabel=GUICtrlCreateLabel("",10,10,$nX,$nY)
    GUICtrlSetBkColor(-1,0xFF00FF)
    $hPicture=GUICtrlCreatePic("",10,10,$nX,$nY)
    
    $hImage1 = _GDIPlus_ImageLoadFromFile(@ScriptDir&'\start1.png')
    $hGraphic1 = _GDIPlus_ImageGetGraphicsContext($hImage1)
    $hImage2 = _GDIPlus_BitmapCreateFromGraphics($nW,$nH,$hGraphic1)
    $hGraphic2 = _GDIPlus_ImageGetGraphicsContext($hImage2)
    $matrix = _GDIPlus_MatrixCreate()
    _GDIPlus_MatrixRotate($matrix, $nAngle)
    _GDIPlus_GraphicsSetTransform($hGraphic2, $matrix)
    _GDIPlus_GraphicsDrawImage($hGraphic2, $hImage1, $nXOffset+$nRotOffsetX, $nYOffset+$nRotOffsetY)
    Local $hBMP1=_GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage2)
    _WinAPI_DeleteObject(GUICtrlSendMsg($hPicture, 0x0172, 0, $hBMP1))
    
    _GDIPlus_MatrixDispose($matrix)
    _GDIPlus_GraphicsDispose($hGraphic1)
    _GDIPlus_GraphicsDispose($hGraphic2)
    _GDIPlus_ImageDispose($hImage1)
    _GDIPlus_ImageDispose($hImage2)
EndFunc

This will draw a GUI with a black background. A pink rectangle the same size as the image will be drawn underneath. The buttons will rotate the image and the rectangle. I found with this that the 90 degree rotation also has the same problem - dropped pixels on the the right side. This can clearly be seen with this script - the pink line on the right side of the image after rotation. I am begining to think that there is a flaw in how this rotation is completed that results in the dropped pixels.

Edit: Not the most efficient code - but demonstrates the point

Edited by YellowLab

You can't see a rainbow without first experiencing the rain.

Link to comment
Share on other sites

Thank the light for the internet. Digging around MSDN I found this function: GDIPlus RotateFlip. It seemed to be what I wanted and doing a search for the function lead me to this autoit post:

http://www.autoitscript.com/forum/index.php?showtopic=101283

Implementing that function works like a charm:

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

Global enum _
    $RotateNoneFlipNone = 0 , _
    $Rotate90FlipNone = 1 , _
    $Rotate180FlipNone = 2 , _
    $Rotate270FlipNone = 3 , _
    $RotateNoneFlipX = 4 , _
    $Rotate90FlipX = 5 , _
    $Rotate180FlipX = 6 , _
    $Rotate270FlipX = 7 , _
    $RotateNoneFlipY = 6 , _
    $Rotate90FlipY = 7 , _
    $Rotate180FlipY = 4 , _
    $Rotate270FlipY = 5 , _
    $RotateNoneFlipXY = 6 , _
    $Rotate90FlipXY = 7 , _
    $Rotate180FlipXY = 0 , _
    $Rotate270FlipXY = 1


$nX=52
$nY=98

$hMain=GUICreate("Rotate Test",350,250,0,0)
GUISetBkColor(0x000000)
$hLabel=GUICtrlCreateLabel("",10,10,$nX,$nY)
GUICtrlSetBkColor(-1,0xFF00FF)
$hPicture=GUICtrlCreatePic("",10,10,$nX,$nY)

_GDIPlus_Startup()
$hImage1 = _GDIPlus_ImageLoadFromFile(@ScriptDir&'\start1.png')
$hBMP1=_GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage1)
_WinAPI_DeleteObject(GUICtrlSendMsg($hPicture, 0x0172, 0, $hBMP1))

$hOriginal = GUICtrlCreateButton("Original",200,10,80,30)
$h90 = GUICtrlCreateButton("90 Rotation",200,50,80,30)
$h180_0=GUICtrlCreateButton("180 Rotation, 0",200,90,80,30)
$h180_1=GUICtrlCreateButton("180 Rotation, 1",200,130,80,30)

GUISetState(@SW_SHOW,$hMain)
While 1
    $nMsg=GUIGetMsg()
    Switch $nMsg
        Case -3
            Exit
        Case $hOriginal
            $nX=52
            $nY=98
            GUICtrlDelete($hPicture)
            GUICtrlDelete($hLabel)
            $hLabel=GUICtrlCreateLabel("",10,10,$nX,$nY)
            GUICtrlSetBkColor(-1,0xFF00FF)
            $hPicture=GUICtrlCreatePic("",10,10,$nX,$nY)
            $hImage1 = _GDIPlus_ImageLoadFromFile(@ScriptDir&'\start1.png')
            $hBMP1=_GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage1)
            _WinAPI_DeleteObject(GUICtrlSendMsg($hPicture, 0x0172, 0, $hBMP1))
            _GDIPlus_ImageDispose($hImage1)
        Case $h90
            $nX=98
            $nY=52
            $nAngle=$Rotate90FlipNone
            _RotateImage($nX,$nY,$nAngle)
        Case $h180_0
            $nX=52
            $nY=98
            $nAngle=$Rotate180FlipNone
            _RotateImage($nX,$nY,$nAngle)
        Case $h180_1
            $nX=52
            $nY=98
            $nAngle=$Rotate180FlipNone
            _RotateImage($nX,$nY,$nAngle)
    EndSwitch
WEnd

GUIDelete($hMain)
_GDIPlus_ImageDispose($hImage1)
_GDIPlus_Shutdown()

Func _RotateImage($nW,$nH,$nRotation)
    GUICtrlDelete($hPicture)
    GUICtrlDelete($hLabel)
    
    $hLabel=GUICtrlCreateLabel("",10,10,$nW,$nH)
    GUICtrlSetBkColor(-1,0xFF00FF)
    $hPicture=GUICtrlCreatePic("",10,10,$nW,$nH)
    
    $hImage1 = _GDIPlus_ImageLoadFromFile(@ScriptDir&'\start1.png')
    DllCall($ghGDIPDll,"int","GdipImageRotateFlip","hwnd",$hImage1,"long",$nAngle)
    Local $hBMP1=_GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage1)
    _WinAPI_DeleteObject(GUICtrlSendMsg($hPicture, 0x0172, 0, $hBMP1))
EndFunc

While it solves my problem of the image rotation, it doesn't answer the original question of where the missing pixels went.

You can't see a rainbow without first experiencing the rain.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...