# Visual Basic > Visual Basic 6 and Earlier >  how can i get the GDI+  declaration functions\types?

## joaquim

how can i get the GDI+  declaration functions\types?
i have find these module: https://github.com/tannerhelland/pd2...rc/GDIPlus.bas
but some types are missed  :Frown: 
for now, i only need the GDIPlus_DrawImage() for draw an image using points array.... but maybe there is a complete declaration function\type file

----------


## wqweto

https://github.com/Planet-Source-Cod...Plus%20API.bas

----------


## joaquim

thank you so much for all
now how can i learn using that functions?
i have a C\C++ tutorial\pdf from MSDN, but they have some differences from C\C++ to VB6.
i need understand, for now, the GdipDrawImagePointsI() or GdipDrawImagePoints()(what changes is from  Float to Long):


```
Public Declare Function GdipDrawImagePointsI Lib "gdiplus" (ByVal graphics As Long, ByVal image As Long, dstpoints As POINTL, ByVal count As Long) As GpStatus
```

how the dstpoints works? is just the 4 points?
from the Master Visual Basic 2010 book: "VB 2010 at Work: The ImageCube Project
As discussed earlier in this tutorial, the DrawImage method can render images on any parallelogram,
not just a rectangle, with the necessary distortion. A way to look at these images is not
as distorted images, but as perspective images. Looking at a printout from an unusual angle is
equivalent to rendering an image within a parallelogram. Imagine a cube with a different image
glued on each side. To display such a cube on your monitor, you must calculate the coordinates
of the cubes edges and then use these coordinates to define the parallelograms on which each
image will be displayed. Figure 4.16 shows a cube with a different image on each side."

and 
"Graphics.DrawImage(img, points())
The array holds three points, which are the top-left, top-right, and bottom-left corners of the
parallelogram. The fourth point is determined uniquely by the other three, and you need not
supply it. The ImageCube sample project, shown later in this tutorial, uses this overloaded form
of the DrawImage method to draw a cube with a different image on each face.
Another interesting form of the method allows you to set the attributes of the image:
Graphics.DrawImage(image, points(), srcRect, units, attributes)
The first two arguments are the same as in the previous forms of the method. The srcRect
argument is a rectangle that specifies the portion of image to draw, and units is a constant
of the GraphicsUnit enumeration. It determines how the units of the rectangle are measured
(pixels, inches, and so on). The last argument is an ImageAttributes object that contains information
about the attributes of the image you want to change (such as the gamma value, and a
transparent color value or color key). The properties of the ImageAttributes class are discussed
shortly."
my question is: "The array holds three points, which are the top-left, top-right, and bottom-left corners of the
parallelogram. The fourth point is determined uniquely by the other three, and you need not
supply it."
can i add the 4 point?
i'm getting problems on other different code, that's why i'm asking.
thank you so much for all

----------


## wqweto

> can i add the 4 point?
> i'm getting problems on other different code, that's why i'm asking.
> thank you so much for all


You can add 4th point but most probably it will be ignored. The text explicitly states that the API can draw parallelograms which are uniquely defined by only 3 points. The API might ignore the extra point of it might explicitly fail, both behaviors are to be expected. 

What is not expected is to actually *use* the 4-th point and skew the image into a random quadrilateral.

cheers,
</wqw>

----------


## jj2007

It is difficult to get documentation on GdiPlus - which is a pity because it offers an awful lot of useful high quality graphic functions. If you don't mind PowerBasic-style declarations: José Roca's help file is an excellent resource

----------


## LaVolpe

One of my favorite sites:
http://www.jose.it-berater.org/gdiplus/iframe/index.htm

----------


## dilettante

How about a phony TrapezoidBlt() operation?  Simplistic and assumes an upright position but you could rotate by adding a PlgBlt() step.




```
Option Explicit

'Faux "TrapezoidBlt" operation.
'
'Quick and dirty: Two PictureBox controls AutoRedraw = True to use their DCs.
'                 Picture1 prefilled with a bitmap to blit.

Private Enum StretchBltModes
    [_SBMFAILED] = 0
    BLACKONWHITE = 1
    WHITEONBLACK = 2
    COLORONCOLOR = 3
    HALFTONE = 4
End Enum

Private Declare Function SetStretchBltMode Lib "gdi32" ( _
    ByVal hDC As Long, _
    ByVal StretchMode As StretchBltModes) As StretchBltModes

Private Declare Function StretchBlt Lib "gdi32" ( _
    ByVal hdcDest As Long, _
    ByVal nXOriginDest As Long, _
    ByVal nYOriginDest As Long, _
    ByVal nWidthDest As Long, _
    ByVal nHeightDest As Long, _
    ByVal hdcSrc As Long, _
    ByVal nXOriginSrc As Long, _
    ByVal nYOriginSrc As Long, _
    ByVal nWidthSrc As Long, _
    ByVal nHeightSrc As Long, _
    Optional ByVal dwRop As RasterOpConstants = vbSrcCopy) As Long

Private Declare Function TransparentBlt Lib "msimg32" ( _
    ByVal hdcDest As Long, _
    ByVal nXOriginDest As Long, _
    ByVal nYOriginDest As Long, _
    ByVal nWidthDest As Long, _
    ByVal hHeightDest As Long, _
    ByVal hdcSrc As Long, _
    ByVal nXOriginSrc As Long, _
    ByVal nYOriginSrc As Long, _
    ByVal nWidthSrc As Long, _
    ByVal nHeightSrc As Long, _
    ByVal crTransparent As Long) As Long

Private Sub TrapezoidBlt(ByVal PctTop As Single, ByVal TranspColor As Long)
    Dim ScanLines As Long
    Dim FullWidth As Long
    Dim ScanWidth As Single
    Dim ScanLeft As Single
    Dim Delta As Single
    Dim sbmOrig As StretchBltModes
    Dim ScanLine As Long

    With Picture1
        Picture2.Width = .Width
        Picture2.Height = .Height
        ScanLines = ScaleY(.ScaleHeight, .ScaleMode, vbPixels)
        FullWidth = ScaleX(.Width, ScaleMode, vbPixels)
        ScanWidth = .ScaleWidth * PctTop / 100
        ScanLeft = (.ScaleWidth - ScanWidth) / 2
        Delta = ScanLeft / ScanLines
        Picture2.BackColor = TranspColor
        sbmOrig = SetStretchBltMode(Picture2.hDC, HALFTONE)
        For ScanLine = 0 To ScanLines - 1
            StretchBlt Picture2.hDC, _
                       ScaleX(ScanLeft, .ScaleMode, vbPixels), _
                       ScanLine, _
                       ScaleX(ScanWidth, .ScaleMode, vbPixels), _
                       1, _
                       .hDC, _
                       0, _
                       ScanLine, _
                       FullWidth, _
                       1
            ScanLeft = ScanLeft - Delta
            ScanWidth = ScanWidth + 2 * Delta
        Next
    End With
    SetStretchBltMode Picture2.hDC, sbmOrig
    TransparentBlt hDC, _
                   0, _
                   0, _
                   ScaleX(ScaleWidth, ScaleMode, vbPixels), _
                   ScaleY(ScaleHeight, ScaleMode, vbPixels), _
                   Picture2.hDC, _
                   0, _
                   0, _
                   FullWidth, _
                   ScanLines, _
                   TranspColor
End Sub

Private Sub Form_Resize()
    If WindowState <> vbMinimized Then
        AutoRedraw = True
        Cls
        TrapezoidBlt 40, &H10101
        AutoRedraw = False
    End If
End Sub
```

----------


## mms_

Is your question in post #3, 
whether or not *GdipDrawImagePointsI* will draw a parallelogram, 
or is it specifically about the 4th point?

If your question is "will it draw a parallelogram"? 
The answer is YES

----------


## passel

> ...
> from the Master Visual Basic 2010 book: "VB 2010 at Work: The ImageCube Project
> As discussed earlier in this tutorial, the DrawImage method can render images on any parallelogram,
> not just a rectangle, with the necessary distortion. A way to look at these images is not
> as distorted images, but as perspective images. Looking at a printout from an unusual angle is
> equivalent to rendering an image within a parallelogram. Imagine a cube with a different image
> glued on each side. To display such a cube on your monitor, you must calculate the coordinates
> of the cubes edges and then use these coordinates to define the parallelograms on which each
> image will be displayed. Figure 4.16 shows a cube with a different image on each side."
> ...


You will get the same code problems using GDI+ as you do now using plgblt, since you are doing the same operation. The DrawImage with an array of points just allows you to do a parallelogram blit at a higher level, and within the GDI+ drawing space (i.e. in the current Graphics object context with the active graphics matrix in play).

The use of the word "perspective images" in the book is misleading. It is not a perspective image. A parallelogram image is isometric.
You can draw isometric blocks, so there is no Z-depth foreshortening nor is there perspective depth calculations to squeeze or expand the texture along the length of the Z axis to give you that perspective view.

If you want to use the parallelogram to draw isometric surfaces, then you can simplify your code and remove the extra perspective calculations done at the end of your coordinate conversions.
If you want to actually draw a texture with perspective then you need to abandon the parallelogram.  You are not drawing parallelograms, you are drawing trapezoids. I'm not sure how many hundreds of times over the last 10 years of your posts we have to say this. I know language is one problem, but parallelograms and trapezoids are geometric terms and should be applicable and describe in most any higher level school curriculum  regardless of the native language it is taught in.

If you want to draw a maze like game, with floor, ceiling and walls, then the code dilettante gave is like the first step in mapping a texture to a trapezoid shape. 
The part that is missing from dilettante's code is a compensation in the loop for depth. The texture is "spread" evenly across the top to bottom of the trapezoid (i.e. the value delta is a constant, and used in directly indexing into the source texture).

You could use plgblt in place of stretchblt in dilettante's code, which would allow drawing at other angles, as dilettante says, but if you want to stay level and run around a maze like world, this isn't necessary.
The plgblt, even used as a direct replacement in dilettante's code, is many times slower than using stretchblt, so I would avoid using it if possible.

For perspective, the index into the source texture needs to be calculated for each line (horizontal line in this case) based on z-depth of that line.
Depending on the values you use, for the closest end of the trapezoid (the bottom), you might be blitting the same line of pixels from the source texture, so the texture is "stretched" at the close end, and gets less stretched as you go up the trapezoid until it is one to one for a while, and then starts skipping lines of the source, so the image shrinks vertically as it continues filling the trapezoid.

That is what you need to do. There isn't an Windows API call that will do that for you. 

There is a GDI+ call to draw a graphics path with perspective, and that is the closest that a Windows API comes to drawing with perspective. But you can't use a graphics path to draw an image with perspective. The path has perspective, but not the brush that fills the path.

----------


## dilettante

Yep, it looks like there is only so much you can do with 2D operations to quickly simulate a 3rd dimension with any fidelity.

----------


## joaquim

passel that's why i'm using the GDI+, but seems that you have right: i don't understand what i'm missing... sorry.
i did i new function that works draw an image:


```
Private Function DrawImage(filename As String, hdc As Long, x As Long, y As Long) As Boolean
    On Error Resume Next
    Dim GDIsi As GdiplusStartupInput, gToken As Long, hGraphics As Long, hBitmap As Long
    GDIsi.GdiplusVersion = 1&
    GdiplusStartup gToken, GDIsi
    If Err Then
          Err.Clear
          Exit Function
    ElseIf gToken = 0& Then
         Exit Function
    End If
    On Error GoTo 0
    Call GdipCreateFromHDC(hdc, hGraphics)
    If hGraphics Then
        Call GdipLoadImageFromFile(StrPtr(filename), hBitmap)
        If hBitmap Then
            GdipDrawImage hGraphics, hBitmap, x, y
            GdipDisposeImage hBitmap
            DrawImage = True
        End If
        GdipDeleteGraphics hGraphics
    End If
    GdiplusShutdown gToken
End Function
```

the image is drawed correctly..
yesterday  i did a new function for use the points:


```
Private Function DrawImagePoints(filename As String, hdc As Long, Points() As POINTL) As Boolean
    On Error Resume Next
    Dim GDIsi As GdiplusStartupInput, gToken As Long, hGraphics As Long, hBitmap As Long
    GDIsi.GdiplusVersion = 1&
    GdiplusStartup gToken, GDIsi
    If Err Then
          Err.Clear
          Exit Function
    ElseIf gToken = 0& Then
         Exit Function
    End If
    On Error GoTo 0
    Call GdipCreateFromHDC(Me.hdc, hGraphics)
    If hGraphics Then
        Call GdipLoadImageFromFile(StrPtr(filename), hBitmap)
        If hBitmap Then
            GdipDrawImagePointsI hGraphics, hBitmap, Points(0), 3
            GdipDisposeImage hBitmap
            DrawImagePoints = True
            
        End If
        GdipDeleteGraphics hGraphics
    End If
    GdiplusShutdown gToken
End Function

//how i use it:
Dim s(4) As POINTL
    s(0).x = Points(0).x
    s(0).y = Points(0).y
    s(1).x = Points(1).x
    s(1).y = Points(1).y
    s(2).x = Points(3).x
    s(2).y = Points(3).y
    s(0).x = Points(0).x
    s(0).y = Points(0).y

    DrawImagePoints "C:\Users\Joaquim Jesus\Documents\Visual Basic 6\World3D\tijolo.jpg", Me.hdc, s
    Me.Refresh
```

the image isn't showed... seems the 'hGraphics' isn't created or something...
what you can tell me?
thanks for the link LaVolte

----------


## mms_

Where how is your Points() array declared and elements assigned?

----------


## joaquim

```
Private Sub DrawPlane(Position As Position3D, size As Size3D, Rotation As Angle3D, WorldSize As Size3D)
    Dim Points(4) As POINTAPI
    Dim NewPoint As POINTAPI
    Dim NewPosition3D(4) As Position3D
    Dim RotatedPosition As Position3D
    
    'Rotate from player position:
    With Player1.Position
       FillPosition3D RotatedPosition, Player1.Position.x + Player1.size.Width / 2, Player1.Position.y + Player1.size.Height / 2, Player1.Position.Z + Player1.size.ZDepth / 2 'Camera Position
    End With
    
    'Get the four vectors
    
    'Floor:
    'Vector1: low-left
    FillPosition3D NewPosition3D(0), Position.x, Position.y, Position.Z + size.ZDepth
    NewPosition3D(0) = Rotate(NewPosition3D(0), Rotation, RotatedPosition)
    
    
    'Vector2: upper-left
    FillPosition3D NewPosition3D(1), Position.x + size.Width, Position.y, Position.Z + size.ZDepth
    NewPosition3D(1) = Rotate(NewPosition3D(1), Rotation, RotatedPosition)
    
    'Vector3: upper-right
    FillPosition3D NewPosition3D(2), Position.x + size.Width, Position.y, Position.Z
    NewPosition3D(2) = Rotate(NewPosition3D(2), Rotation, RotatedPosition)
    
    
    'Vector4: low-right
    FillPosition3D NewPosition3D(3), Position.x, Position.y, Position.Z
    NewPosition3D(3) = Rotate(NewPosition3D(3), Rotation, RotatedPosition)
    
    'Testing if the plane is on screen:
        
    If ((IsOnCamera(NewPosition3D(0), camera1.Position, camera1.size) = False) _
        And (IsOnCamera(NewPosition3D(1), camera1.Position, camera1.size) = False) _
        And (IsOnCamera(NewPosition3D(2), camera1.Position, camera1.size) = False) _
        And (IsOnCamera(NewPosition3D(3), camera1.Position, camera1.size) = False)) Then
        'Exit Sub
    End If
    
    If (IsOnCamera(NewPosition3D(0), camera1.Position, camera1.size) = False) Then
       ' NewPosition3D(0) = GetInCamVector(NewPosition3D(0), NewPosition3D(1))
    End If
    
    If (IsOnCamera(NewPosition3D(1), camera1.Position, camera1.size) = False) Then
        'NewPosition3D(1) = GetInCamVector(NewPosition3D(1), NewPosition3D(0))
    End If
    
    If (IsOnCamera(NewPosition3D(2), camera1.Position, camera1.size) = False) Then
        'NewPosition3D(2) = GetInCamVector(NewPosition3D(1), NewPosition3D(2))
        'NewPosition3D(2).X = NewPosition3D(3).X
    End If
    
    
    If (IsOnCamera(NewPosition3D(3), camera1.Position, camera1.size) = False) Then
        'NewPosition3D(3) = NewPosition3D(0)
        'NewPosition3D(3).X = NewPosition3D(2).X
    End If
    
   
    
    'Convert all 3D vectors to 2D vectors(for screen):
    Dim I As Integer
    For I = 0 To UBound(Points)
        Points(I) = ConvertPositon3DTo2D(NewPosition3D(I), WorldSize)
    Next I
    
    'change the brush and pen:
    FillStyle = vbFSSolid
    'FillColor = vbRed
    
    'Draw the polygn:
    DrawStyle = DrawStyleConstants.vbInvisible
    Polygon Me.hdc, Points(0), 4
    
    'draw the texture:
    Dim TexturePoints(3) As POINTAPI
    TexturePoints(0) = Points(0) 'upper-left
    TexturePoints(1) = Points(1) 'upper-right
    TexturePoints(2) = Points(3) 'lower-left
    
    Label2.Caption = "TexturePoints(0): (" + CStr(TexturePoints(0).x) + ", " + CStr(TexturePoints(0).y) + ")"
    Label2.Caption = Label2.Caption + vbNewLine + "TexturePoints(1): (" + CStr(TexturePoints(1).x) + ", " + CStr(TexturePoints(1).y) + ")"
    Label2.Caption = Label2.Caption + vbNewLine + "TexturePoints(2): (" + CStr(TexturePoints(2).x) + ", " + CStr(TexturePoints(2).y) + ")"
    
    
    Label3.Caption = "Points(0): (" + CStr(Points(0).x) + ", " + CStr(Points(0).y) + ")"
    Label3.Caption = Label3.Caption + vbNewLine + "Points(1): (" + CStr(Points(1).x) + ", " + CStr(Points(1).y) + ")"
    Label3.Caption = Label3.Caption + vbNewLine + "Points(2): (" + CStr(Points(2).x) + ", " + CStr(Points(2).y) + ")"
    Label3.Caption = Label3.Caption + vbNewLine + "Points(3): (" + CStr(Points(3).x) + ", " + CStr(Points(3).y) + ")"
    Dim s(4) As POINTL
    s(0).x = Points(0).x
    s(0).y = Points(0).y
    s(1).x = Points(1).x
    s(1).y = Points(1).y
    s(2).x = Points(3).x
    s(2).y = Points(3).y
    s(0).x = Points(0).x
    s(0).y = Points(0).y
    'If (PlgBlt(Me.hDC, TexturePoints(0), Picture1.hDC, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, &O0, &O0, &O0) = 0) Then MsgBox CStr(GetLastError())
    DrawImagePoints "C:\Users\Joaquim Jesus\Documents\Visual Basic 6\World3D\tijolo.jpg", Me.hdc, s
    Me.Refresh
End Sub
```



```
Private Function ConvertPositon3DTo2D(Position As Position3D, World3DSize As Size3D) As POINTAPI
    
    Dim ConvertedPosition As POINTAPI
    Dim PosZZDepth As Long
    
    Dim Width As Double
    Dim Height As Double
    
    'sum Z position with cam world distance:
    PosZZDepth = Position.Z + World3DSize.distance
    If (PosZZDepth = 0) Then PosZZDepth = 1 'avoiding division by zero
    
    'getting center of the screen center:
    If (World3DSize.Width = 0) Then World3DSize.Width = 1 'avoiding division by zero
    Width = World3DSize.Width / 2
    If (World3DSize.Height = 0) Then World3DSize.Height = 1 'avoiding division by zero
    Height = World3DSize.Height / 2
    
    
    'avoid drawing on back of the camera:
    If (PosZZDepth <= World3DSize.distance) Then
         PosZZDepth = 1
         'World3DSize.distance = 1
    End If
    
    'convert 3D(X, Y, Z) to 2D(X,Y):
    'ConvertedX = (ActualX * CamDistance /(CamDistance + ZPosition)) + HalfCenterOfWidth
    'ConvertedY = (ActualY * CamDistance /(CamDistance + ZPosition)) + HalfCenterOfHeight
    ConvertedPosition.x = (Position.x * World3DSize.distance / PosZZDepth) + Width
    ConvertedPosition.y = (Position.y * World3DSize.distance / PosZZDepth) + Height
    
    ConvertPositon3DTo2D = ConvertedPosition
End Function
Private Function ConvertDegreesToRadians(Rotation As Angle3D) As Angle3D
    Dim deg2Rad As Double
    deg2Rad = Pi / 180
    
    ConvertDegreesToRadians.x = Rotation.x * deg2Rad
    ConvertDegreesToRadians.y = Rotation.y * deg2Rad
    ConvertDegreesToRadians.Z = Rotation.Z * deg2Rad
End Function

Private Function Rotate(Position As Position3D, Rotation As Angle3D, PositionRotated As Position3D) As Position3D
    Dim ConvertedPosition As Position3D
    Dim RotationInRads As Angle3D
    
    RotationInRads = ConvertDegreesToRadians(Rotation)
    ConvertedPosition = Position
    ConvertedPosition.x = Position.x - PositionRotated.x
    ConvertedPosition.y = Position.y - PositionRotated.y  'reversed because Y increments down
    ConvertedPosition.Z = Position.Z - PositionRotated.Z
    Dim T As Position3D
    
    'Z axis  (Roll)
    T = ConvertedPosition
        ConvertedPosition.x = T.x * Cos(RotationInRads.Z) - T.y * Sin(RotationInRads.Z)
        ConvertedPosition.y = T.x * Sin(RotationInRads.Z) + T.y * Cos(RotationInRads.Z)
    
    'X axis  (Pitch)
    T = ConvertedPosition
        ConvertedPosition.y = T.y * Cos(RotationInRads.x) - T.Z * Sin(RotationInRads.x)
        ConvertedPosition.Z = T.y * Sin(RotationInRads.x) + T.Z * Cos(RotationInRads.x)
  
    'Y axis  (Yaw)
    T = ConvertedPosition
        ConvertedPosition.x = T.Z * Sin(RotationInRads.y) + T.x * Cos(RotationInRads.y)
        ConvertedPosition.Z = T.Z * Cos(RotationInRads.y) - T.x * Sin(RotationInRads.y)
        
        'Go back to the new position:
        ConvertedPosition.x = ConvertedPosition.x + PositionRotated.x
        ConvertedPosition.y = ConvertedPosition.y + PositionRotated.y
        ConvertedPosition.Z = ConvertedPosition.Z + PositionRotated.Z
        
    Rotate = ConvertedPosition
End Function
```

----------


## mms_

Well assuming your Points() array has valid data your call

*            GdipDrawImagePointsI hGraphics, hBitmap, Points(0), 3*

looks fine to me.

I tested similar here and it works OK

try:

*status = GdipDrawImagePointsI(hGraphics, hBitmap, Points(0), 3)*

and make sure status reports back as Zero

----------


## joaquim

```
On Error GoTo 0
    Call GdipCreateFromHDC(Me.hdc, hGraphics)
    If hGraphics Then
        Call GdipLoadImageFromFile(StrPtr(filename), hBitmap)
        If hBitmap Then
            MsgBox "hey" 'ins't called
            GdipDrawImagePointsI hGraphics, hBitmap, Points(0), 3
```

the message box isn't showed.. the image is on disk.. but i use the 'images' folder

----------


## joaquim

```
status = GdipLoadImageFromFile(StrPtr(filename), hBitmap)
        MsgBox CStr(status)
```

 i get '3'

----------


## joaquim

"OutOfMemory : Indicates that the operating system is out of memory and could not allocate memory to process the function call"

----------


## LeandroA

hello GDI + can NOT do what I think it wants to do, I have seen with DirectDraw or I think with Cairo

years ago with gdi I did a limited trick to create a perspective shaped rotation effect
http://leandroascierto.com/foro/inde...sg1635#msg1635

----------


## LaVolpe

> ```
> On Error GoTo 0
>     Call GdipCreateFromHDC(Me.hdc, hGraphics)
>     If hGraphics Then
>         Call GdipLoadImageFromFile(StrPtr(filename), hBitmap)
>         If hBitmap Then
>             MsgBox "hey" 'ins't called
>             GdipDrawImagePointsI hGraphics, hBitmap, Points(0), 3
> ```
> ...


If the image file cannot be opened exclusively by GDI+ (i.e., open it and lock it), then GdipLoadImageFromFile fails. The error code of 3 does not always mean "out of memory". It seems that GDI+ uses that error code like VB uses error code 5 "Invalid procedure call or argument"

----------


## [citation-needed]

For reference, GdipDrawImagePointsI can also fail if the passed points all lie on (or nearly on) the same line.  

This case wouldn't be unexpected for arbitrary 3D projections, but as already pointed out by many, GdipDrawImagePointsI is not a useful API for this anyway.  

(You can also review GDI+ flat function calls declares via MSDN, which is probably preferable as Jose Roca's documentation is not always accurate.)

From GdipDrawImagePointsI:




> The value of the count parameter must equal 3 to specify the coordinates of the upper-left corner, upper-right corner, and lower-left corner of the parallelogram. The coordinate of the lower-right corner is calculated using the three given coordinates, the width, and the height of the image. The portion of the source image to be drawn is scaled to fit the parallelogram.

----------


## joaquim

wow.. the DrawImage():


```
Private Function DrawImage(FileName As String, hDC As Long, x As Long, y As Long) As Boolean
    On Error Resume Next
    Dim GDIsi As GDIPlusStartupInput, gToken As Long, hGraphics As Long, hBitmap As Long
    GDIsi.GDIPlusVersion = 1&
    GdiplusStartup gToken, GDIsi
    If Err Then
          Err.Clear
          Exit Function
    ElseIf gToken = 0& Then
         Exit Function
    End If
    On Error GoTo 0
    Call GdipCreateFromHDC(hDC, hGraphics)
    If hGraphics Then
        Call GdipLoadImageFromFile(StrPtr(FileName), hBitmap)
        If hBitmap Then
            GdipDrawImage hGraphics, hBitmap, x, y
            GdipDisposeImage hBitmap
            DrawImage = True
        End If
        GdipDeleteGraphics hGraphics
    End If
    GdiplusShutdown gToken
End Function
```

works on a new project... but not on my project  :Frown: 
i will test the DrawImagePoints() on new project.
the only difference is that i use a timer on my 3D project.. somethings make me confused

----------


## joaquim

i found the big problem: everyone can make their own types\enums\consts names... and if i'm not prepared for it, i can make some problems.
is there anyway for we detect these type of errors?

now the DrawImagePoints() give me the image, but, like passel said, i get the same result.


```
Private Function DrawImagePoints(FileName As String, hDC As Long, ByRef Points() As POINTL) As Boolean
    On Error Resume Next
    Dim GDIsi As GDIPlusStartupInput, gToken As Long, hGraphics As Long, hBitmap As Long
    GDIsi.GDIPlusVersion = 1&
    GdiplusStartup gToken, GDIsi
    Dim status As GpStatus
    
    If Err Then
          Err.Clear
          Exit Function
    ElseIf gToken = 0& Then
         Exit Function
    End If
    On Error GoTo 0
    Call GdipCreateFromHDC(Me.hDC, hGraphics)
    If hGraphics Then
        status = GdipLoadImageFromFile(StrPtr(FileName), hBitmap)
        If hBitmap Then
            GdipDrawImagePointsI hGraphics, hBitmap, Points(0), 3
            GdipDisposeImage hBitmap
            DrawImagePoints = True
            
        End If
        GdipDeleteGraphics hGraphics
    End If
    GdiplusShutdown gToken
End Function
```

how i use it:


```
Dim s(4) As POINTL
    s(0).x = Points(0).x
    s(0).y = Points(0).y
    s(1).x = Points(1).x
    s(1).y = Points(1).y
    s(2).x = Points(3).x
    s(2).y = Points(3).y
    'If (PlgBlt(Me.hDC, TexturePoints(0), Picture1.hDC, 0, 0, Picture1.ScaleWidth, Picture1.ScaleHeight, &O0, &O0, &O0) = 0) Then MsgBox CStr(GetLastError())
    DrawImagePoints "C:\tijolo.jpg", Me.hDC, s
```

result:
https://imgur.com/a/hypD7cp
the image is showed, but the 4 point, like with PlgBlt(), isn't correctly calculated  :Frown: 
what i did wrong? the passel had said something about it, but i still confused  :Frown:

----------


## mms_

In your posted image, I cannot make out the co-ordinates in the Points() array.
What are the points?

----------


## joaquim

the points() are the filled shaped coordinates

----------


## passel

> ...
> the image is showed, but the 4 point, like with PlgBlt(), isn't correctly calculated 
> what i did wrong? the passel had said something about it, but i still confused


What you did wrong is try to fill a trapezoid area using a parallelogram shape.

A trapezoid shape is not a parallelogram shape. 

Those are geometric figures.  Look them up.

A trapezoid is not a parallelogram. 
A trapezoid is not a parallelogram.
A trapezoid is not a parallelogram.

If you used code based on dilettante's in post #7, you could at least fill the trapezoid with the texture. 
It won't be adjusted for depth, but it will at least fill the trapezoid shape so do what you're trying to do with plgblt.

----------


## passel

> In your posted image, I cannot make out the co-ordinates in the Points() array.
> What are the points?


Points(0): (370,242)
Points(1): (392,242)
Points(2): (516,348)
Points(3): (264,348)

The points define the red trapezoid, wide at the bottom, narrow at the top. Just try to "fill" the brick pattern with red in the image to visualize the trapezoid.

----------


## passel

Just as a quick example of compensating for depth, I modified dilettante's code, using the percentage value he used (currently 40%, i.e. the top of the trapezoid is 40% of the size of the bottom of the trapezoid) to modify the source scanline picked to be drawn to the destination scanline.

So, rather than being a 1 to 1 ratio over the entire length from top to bottom, the source scanline is incrementing at a greater ratio (1 to 1.4) at the top and reaches 1 to 1 at the bottom.
This compresses (vertically) the image at the top, and is the source's  full pixel size for the last line at the bottom.

This is a bit arbitrary, using the percentage size difference between top and bottom to represent the scaling due to Z depth in 3D, but it is representative of the desired result in a fairly easy computation.
I just added a scale factor (ScanZ) and a value to decrement the scale factor linearly by (ScanZDec).  The Z-depth perspective calculation is a straight division by z depth, so the result is analogous.

The updated trapezoidBlt sub, of the code in post #7.


```
Private Sub TrapezoidBlt(ByVal PctTop As Single, ByVal TranspColor As Long)
    Dim ScanLines As Long
    Dim FullWidth As Long
    Dim ScanWidth As Single
    Dim ScanLeft As Single
    Dim Delta As Single
    Dim sbmOrig As StretchBltModes
    Dim ScanLine As Long
    Dim ScanZ As Single
    Dim ScanZDec As Single
    
    With Picture1
        Picture2.Width = .Width
        Picture2.Height = .Height
        ScanLines = ScaleY(.ScaleHeight, .ScaleMode, vbPixels)
        Debug.Print ScanLines
        FullWidth = ScaleX(.Width, ScaleMode, vbPixels)
        ScanWidth = .ScaleWidth * PctTop / 100
        ScanLeft = (.ScaleWidth - ScanWidth) / 2
        Delta = ScanLeft / ScanLines
        Picture2.BackColor = TranspColor
        sbmOrig = SetStretchBltMode(Picture2.hDC, HALFTONE)
        ScanZ = 1 + (PctTop / 100)
        ScanZDec = (PctTop / 100) / ScanLines
        
        For ScanLine = 0 To ScanLines - 1
            StretchBlt Picture2.hDC, _
                       ScaleX(ScanLeft, .ScaleMode, vbPixels), _
                       ScanLine, _
                       ScaleX(ScanWidth, .ScaleMode, vbPixels), _
                       1, _
                       .hDC, _
                       0, _
                       ScanLine * ScanZ, _
                       FullWidth, _
                       1
            ScanLeft = ScanLeft - Delta
            ScanWidth = ScanWidth + 2 * Delta
            ScanZ = ScanZ - ScanZDec
        Next
    End With
    SetStretchBltMode Picture2.hDC, sbmOrig
    TransparentBlt hDC, _
                   0, _
                   0, _
                   ScaleX(ScaleWidth, ScaleMode, vbPixels), _
                   ScaleY(ScaleHeight, ScaleMode, vbPixels), _
                   Picture2.hDC, _
                   0, _
                   0, _
                   FullWidth, _
                   ScanLines, _
                   TranspColor
End Sub
```

The difference may appear subtle at first, but look at how the lines of text align from left to right image, especially at the bottom, i.e. you have four lines on the left in the space taken by three lines on the right.

----------


## dilettante

My hack was just a hack, but at least this improves it if perspective is what you're after.  Sounds like a reasonable assumption though.

I haven't seen another simple way to blit to a trapezoid though outside of using some 3D library.  Oddly enough many video cards do seem to support trapezoids.  Weird that GDI never supported it.



```
/* Device Capability Masks: */
:
:
/* Polygonal Capabilities */
#define PC_NONE             0   /* Polygonals not supported         */
#define PC_POLYGON          1   /* Can do polygons                  */
#define PC_RECTANGLE        2   /* Can do rectangles                */
#define PC_WINDPOLYGON      4   /* Can do winding polygons          */
#define PC_TRAPEZOID        4   /* Can do trapezoids                */
#define PC_SCANLINE         8   /* Can do scanlines                 */
#define PC_WIDE             16  /* Can do wide borders              */
#define PC_STYLED           32  /* Can do styled borders            */
#define PC_WIDESTYLED       64  /* Can do wide styled borders       */
#define PC_INTERIORS        128 /* Can do interiors                 */
#define PC_POLYPOLYGON      256 /* Can do polypolygons              */
#define PC_PATHS            512 /* Can do paths                     */
```

... or have I missed something?

----------


## joaquim

ok.. i need understand: what is the difference between trapezoid and parallelogram shapes?
PctTop is what? the start position? i need understand the start positions and their width's for i use the  function....

----------


## LaVolpe

> ok.. i need understand: what is the difference between trapezoid and parallelogram shapes?


http://www.differencebetween.info/di...rallel%20sides.

----------


## dilettante

> PctTop is what?


It was the fraction of the bottom's width to use for the top, as a percent.

----------


## joaquim

the trapezoidBlt() draws from X zero(just using the form entire size).... can i start on X=100 and Y=100?
the PosY = PctTop + Y? and PosX = Width + Y?

----------


## dilettante

Why not?  Tweak away, it was merely a minimal demo.

----------


## mms_

The link that *LeandroA* provides in post #18 
is to his project that does the same but uses GDI+

----------


## The trick

What's about Direct3D? You can render any 3D polygon:

----------


## passel

> What's about Direct3D? You can render any 3D polygon:
> ...


This is an on-going, multiyear project.



> i want draw the image\cube using Geometric Math for learn it. i know that theres several libraries for it... but i want to learn draw the cube, camera and the move....

----------


## ISAWHIM

Made it less "jagged" on the ends.

First thing to do is change all the "Twips" in the forms to "pixels". Both picture-boxes AND the form itself.

Changed singles to doubles and added Int(double math), to force it to whole-pixels instead of error-prone floats. Also changed the slightly slower /2 into *0.5 which is a float, and /100 into *0.01 which is also a little faster. (Multiplication is faster than division and float to float is faster than int to float. 2 is assumed to be an int/long, unless you add # so it is 2# or add an actual decimal place to the number.)

The jagged edges were from nasty "bankers rounding"... as well as horrible float to long conversion. (Int is safe for most screens)



```
Private Sub TrapezoidBlt(ByVal PctTop As Single, ByVal TranspColor As Long)
    Dim ScanLines As Long
    Dim FullWidth As Long
    Dim ScanWidth As Double
    Dim ScanLeft As Double
    Dim Delta As Double
    Dim sbmOrig As StretchBltModes
    Dim ScanLine As Long
    Dim ScanZ As Double
    Dim ScanZDec As Double
    
    With Picture1
        Picture2.Width = .Width
        Picture2.Height = .Height
        ScanLines = ScaleY(.ScaleHeight, .ScaleMode, vbPixels)
        'Debug.Print ScanLines
        FullWidth = ScaleX(.Width, ScaleMode, vbPixels)
        ScanWidth = .ScaleWidth * PctTop * 0.01
        ScanLeft = (.ScaleWidth - ScanWidth) * 0.5
        Delta = ScanLeft / ScanLines
        Picture2.BackColor = TranspColor
        sbmOrig = SetStretchBltMode(Picture2.hDC, HALFTONE)
        ScanZ = 1 + (PctTop * 0.01)
        ScanZDec = (PctTop * 0.01) / ScanLines
        
        For ScanLine = 0 To ScanLines - 1
            StretchBlt Picture2.hDC, _
                       Int(ScaleX(ScanLeft, .ScaleMode, vbPixels)), _
                       ScanLine, _
                       Int(ScaleX(ScanWidth, .ScaleMode, vbPixels)), _
                       1, _
                       .hDC, _
                       0, _
                       Int(ScanLine * ScanZ), _
                       FullWidth, _
                       1
            ScanLeft = ScanLeft - Delta
            ScanWidth = ScanWidth + 2 * Delta
            ScanZ = ScanZ - ScanZDec
        Next
    End With
    SetStretchBltMode Picture2.hDC, sbmOrig
    TransparentBlt hDC, _
                   0, _
                   0, _
                   Int(ScaleX(ScaleWidth, ScaleMode, vbPixels)), _
                   Int(ScaleY(ScaleHeight, ScaleMode, vbPixels)), _
                   Picture2.hDC, _
                   0, _
                   0, _
                   FullWidth, _
                   ScanLines, _
                   TranspColor
End Sub
```

Ten years later and this code is still going strong.  :Smilie:

----------


## -Franky-

Hi
Create a path object with GdipCreatePath, draw something in the phat object with the appropriate GDI+ Phat APIs. e.g. with GdipAddPathString a text. You can then manipulate the phat object with GdipWarpPath. A simple example is here: https://www.activevb.de/tipps/vb6tipps/tipp0672.html

With Direct2D: https://learn.microsoft.com/en-us/wi...d/3d-transform or https://learn.microsoft.com/en-us/wi...tive-transform

a spinning cube: http://www.activevb.de/cgi-bin/uploa...oad.pl?id=3386

----------

