Results 1 to 5 of 5

Thread: Cookie Twist - Rotate circular selection

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Lightbulb Cookie Twist - Rotate circular selection

    The effect is to let the user define a round "cookie" selection in an image and then "twist" it -180 to 180 degrees.


    Unzip into a folder. Copy a large picture into the Project folder and rename it "sample.jpg" or update this line:

    Code:
    Private Const SAMPLE_PIC_FILE As String = "sample.jpg"
    • Run the program.
    • Make a circular selection by left-clicking at the center then dragging out to establish the radius.
    • Then you can use the Up/Down control to set a rotation angle in degrees.
    • After that you can click on the rotation Command button linked to the Up/Down to perform the desired rotation.
    • Make a new selection, or click on the Reload button.



    The "work image" is scaled to fit the Form. You can click the Restore button in the caption bar to unmaximize, and then drag to resize the Form to various sizes.

    That actual clipping and rotation occurs on the original image however, which can be larger or smaller than the area displayed within the Form.

    The user interface isn't very refined, but should give you the idea. The scale factor in % is displayed in the caption bar to give you some idea of the scaling that is active.


    The Pic object holds the original or edited image, so you can use any code you can already find here in the CodeBank for saving a bitmap-type IPicture/StdPicture to disk with or without compression. Even VB's SavePicture works, though it can only save as an uncompressed BMP image file.
    Attached Files Attached Files
    Last edited by dilettante; Sep 6th, 2021 at 08:30 AM.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Cookie Twist - Rotate circular selection

    In response to a private message:

    No, this is not a usable graphics utility program and it is not meant to be.

    It demonstrates a few things you might use though:

    • Scaling an image to fit the Form without scrollbars. Not a substitute for variable magnification and scrolling, but this was more of an example of the other features.
    • Working on an image of a different actual size than the scaled size displayed.
    • Circular "rubberband" selection.
    • Use of PlgBlt() for image rotation.
    • Use of GDI clip regions, in this case a circular one.
    • Updating the bitmap held within an IPicture/StdPicture object. No need to paint to a new bitmap and wrap that as a new IPicture. IPicture was used here because its Render() method is slightly friendlier than the one exposed by the StdPicture interface.


    With some changes you can also use PlgBlt() to do vertical and/or horizontal flips.
    Last edited by dilettante; Sep 6th, 2021 at 12:31 PM.

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Cookie Twist - Rotate circular selection

    Slightly trickier, Star Twist instead.

    Replace the region creation API with this one:

    Code:
    Private Enum POLYFILL_MODES
        ALTERNATE = 1
        WINDING = 2
        [_POLYFILL_LAST] = 2
    End Enum
    
    Private Declare Function CreatePolygonRgn Lib "gdi32" ( _
        ByRef Points As POINTL, _
        ByVal nPoints As Long, _
        Optional ByVal fnPolyFillMode As POLYFILL_MODES = WINDING) As Long
    Replace the subroutine:

    Code:
    Public Sub Rotate( _
        ByVal Picture As stdole.IPicture, _
        ByVal CenterX As Long, _
        ByVal CenterY As Long, _
        ByVal Radius As Long, _
        ByVal Rotation As Double, _
        ByVal ScaleFactor As Double)
        'CenterX, CenterY, Radius are in scaled pixels on entry.
    
        Dim Points(2) As POINTL
        Dim I As Long
        Dim RotatedPoints(2) As POINTL
        Dim VertexScale As Double
        Dim RegionPoints(9) As POINTL
        Dim hdcScreen As Long
        Dim hdcPicture As Long
        Dim hbmPictureOrig As Long
        Dim sbModeOrig As StretchBltModes
        Dim hRegion As Long
        Dim Result As Long
        Dim LastDllError As Long
    
        'Rescale then start Points() with center at (0, 0):
        CenterX = Int(CenterX / ScaleFactor + 0.5)
        CenterY = Int(CenterY / ScaleFactor + 0.5)
        Radius = Int(Radius / ScaleFactor + 0.5)
        Points(0).X = -Radius
        Points(0).Y = -Radius
        Points(1).X = Radius
        Points(1).Y = Points(0).Y
        Points(2).X = Points(0).X
        Points(2).Y = Radius
        'Degrees to radians:
        Rotation = Rotation * PI / 180
        'Adjust center to the target center and rotate Points():
        For I = 0 To 2
            RotatedPoints(I).X = CenterX _
                               + Int(Points(I).X * Cos(Rotation) - Points(I).Y * Sin(Rotation) + 0.5)
            RotatedPoints(I).Y = CenterY _
                               + Int(Points(I).X * Sin(Rotation) + Points(I).Y * Cos(Rotation) + 0.5)
        Next
        'Adjust center to the target center in a similar manner for the star:
        For I = 0 To 9
            'Indent odd vertices:
            If I Mod 2 Then VertexScale = Radius * 0.28 Else VertexScale = Radius
            RegionPoints(I).X = CenterX _
                              - VertexScale * Cos(Rotation + PI * 2 * I / 5# + PI / 2)
            RegionPoints(I).Y = CenterY _
                              - VertexScale * Sin(Rotation + PI * 2 * I / 5# + PI / 2)
        Next
        hdcScreen = GetDC(WIN32_NULL)
        hdcPicture = CreateCompatibleDC(hdcScreen)
        ReleaseDC WIN32_NULL, hdcScreen
        hbmPictureOrig = SelectObject(hdcPicture, Picture.Handle)
        sbModeOrig = SetStretchBltMode(hdcPicture, sbmHalftone)
        hRegion = CreatePolygonRgn(RegionPoints(0), 10)
        SelectClipRgn hdcPicture, hRegion
        DeleteObject hRegion 'Don't need it, the hDC makes a copy.
        Result = PlgBlt(hdcPicture, _
                        RotatedPoints(0), _
                        hdcPicture, _
                        CenterX - Radius, _
                        CenterY - Radius, _
                        Radius * 2, _
                        Radius * 2, _
                        WIN32_NULL, _
                        0, _
                        0)
        LastDllError = Err.LastDllError
        SelectClipRgn hdcPicture, WIN32_NULL
        SetStretchBltMode hdcPicture, sbModeOrig
        SelectObject hdcPicture, hbmPictureOrig
        DeleteDC hdcPicture
        If Result = 0 Then
            Err.Raise &H8004C700, TypeName(Me), "PlgBlt error " & CStr(LastDllError)
        End If
    End Sub
    The changes are actually pretty minor. You could vary the "indenting" factor of the odd vertices (in red above) to create a chubbier or skinnier star "cutout."

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Cookie Twist - Rotate circular selection

    You should find it pretty easy to change the region shape to something like a pentagon, triangle, etc.

  5. #5
    Lively Member
    Join Date
    Mar 2015
    Posts
    104

    Re: Cookie Twist - Rotate circular selection

    Love this sort of code. Will experiment a bit. Thankyou dilettante.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width