Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Image / Picture Guru's Please Help 1

Status
Not open for further replies.

TyGwyn

Programmer
Oct 5, 2005
31
GB
I have created a Bitmap image into a picbox from an ascii string, I have to rotate this through 90deg, which I have done using pset and placed the result into another picbox, it works fine and displays on the screen great, but if I print the form using me.printform the picbox is empty, and if I try to save the picture
SavePicture Me.picbox.Picture, "Bcode.bmp" it saves an empty image, where has the image gone that is displayed on my screen?
 
Pset, eh? The following thread shows my SetWorldTransform method of rotating bitmaps which is much faster than Pset (or any of the MSDN article solutions). It also explains where your 'missing' image has got to and how to fix it: thread222-535523
 
Thanks have not tried your code yet strongm, in theory my own routine should work, even though slow it may be, autoredraw is already set to true for the destination picbox and even after the picbox.refresh the contents still do not appear in the printed image?
 
Sorry, wasn't suggesting that your rotation code wasn't working, just noting the horrendous speed issue (particularly for larger bitmaps).

As for the autoredraw and refresh problem, the problem will be that the target picture in the picturebox has never been initialised, so what you need to do is

targetpicturebox.autoredraw=true
AllYourPsetCode
targetpicturebox.picture=targetpicturebox.image
 
Amazing, that last line of code sorted it. would never of found that one myself, thanks again...your right about the speed of your transform code much quicker than mine and working great in my routine now (royalties to follow), just a twiddle with the X and Y's to suit my pic size, brilliant.

Thanks again for pointing me towards the light.

Adam
 
Just a quick question, this only appears to work if the picbox the image is being transferred from is visible and on top, if there is anything covering the picbox then this is what gets rotated, is there a way around this? other than the obvious making the picbox visible=false after the transform.
 
Make sure that the Autoredraw property of the source picbox is also set to True. I think it would fix the problem.

Another very simple method for rotating images is to use the PlgBlt function. This function is simpler in use than the SetWorldTransform function and allows you to fit a source rectangle into a destination parellelogram.

This offers a variety of affine transformations including stretching, skewing, rotation, scaling, reflection and translation.

Following example shows how to use this function for rotating images at 45° and 90°.
___
[tt]
Private Declare Function PlgBlt Lib "gdi32" (ByVal hdcDest As Long, lpPoint As POINTAPI, ByVal hdcSrc As Long, ByVal nXSrc As Long, ByVal nYSrc As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hbmMask As Long, ByVal xMask As Long, ByVal yMask As Long) As Long
Private Type POINTAPI
x As Long
y As Long
End Type

Private Sub Form_Load()
AutoRedraw = True
Font = "Times New Roman"
FontSize = 72
Print " E"

Dim pt(2) As POINTAPI

'rotate at 45°
pt(0).x = 150: pt(0).y = 0 'top-left
pt(1).x = 220: pt(1).y = 70 'top-right
pt(2).x = 80: pt(2).y = 70 'bottom-left
PlgBlt hDC, pt(0), hDC, 0, 0, 100, 100, 0, 0, 0

'rotate at 90°
pt(0).x = 300: pt(0).y = 0 'top-left
pt(1).x = 300: pt(1).y = 100 'top-right
pt(2).x = 200: pt(2).y = 0 'bottom-left
PlgBlt hDC, pt(0), hDC, 0, 0, 100, 100, 0, 0, 0
End Sub[/tt]
___

If you just want to rotate ASCII strings, as mentioned in your post, you can use CreateFont or CreateFontIndirect functions to create fonts which can render text at any angle upto the resolution of 1/10th of a degree.

However, in my opinion, this method is more complex than the above method and is limited to text rendering only.
 
I believe we mentioned PlgBlt in the thread I referenced.

The main advantage of the SetWorldTransform method is that it is dramatically more flexible than PlgBlt (in that we can do shears, rotations and reflections all in one go), and that once the transform is in place all GDI drawing operations are affected by it (so we can draw as if to the untransformed DC and it will render transformed)
 
The value of the autoredraw on both pic boxes are set to true, it appears that when the image is copied it moves "pixels" that are displayed, from the image coordinates whether the picbox is visible or on top, and it does not move the image that is contained within the picbox. Does this sound right?
 
It apears to be a quirk of working with BitBlt and SetWorldTransform when working with a DC that is on the desktop (in normal circumstances you actually have to specify CAPTUREBLT as the method of blitting to achieve this affect)

Normally I'd be working with a memory DC, and that solves the problem in this scenario. Here's a partially reworked TransformAndDraw function that uses this (in reality, I'd probably redesign TransformAndDraw - as TransformPicture - so that internally it used two memory DCs, one for source and one for target, and took a source StdPic as a parameter, returning the transformed result in another StdPic).

Firstly, the modified TransformAndDraw requires the following declarations:
Code:
[blue]Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function GetObject Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
Private Declare Function GetDesktopWindow Lib "user32" () As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private Declare Function DeleteDC Lib "gdi32" (ByVal hdc As Long) As Long[/blue]
The sub itself now looks like this (this is actually a modified version of a slighly later variant of the code provided in the thread I referenced earlier but, apart from the brand new memory DC stuff, the variations are minor):
Code:
[blue]Private Sub TransformAndDraw(ByVal hdcTarget As Long, ByVal hdcSource As Long, ByVal aboutX As Long, ByVal aboutY As Long, ByVal rotate As Single)
    Dim myXForm As XFORM
    Dim mypoint As POINTAPI
    
    Dim MemDC As Long
    Dim oldBMP As Long
    
    ' tek-tips chages: introduce a memory DC rather than directly using DC of source
    ' picture box; this avoids unexpected beahviour of bitblt
    
    ' Create a memory DC compatible with the desktop
    MemDC = CreateCompatibleDC(GetDC(GetDesktopWindow()))
    ' Select our bitmap into it
    oldBMP = SelectObject(MemDC, Picture2.Picture.Handle)
    
    ' grab original settings so we can restore
    GetWorldTransform hdcTarget, gOldWorld

    SetGraphicsMode hdcTarget, GM_ADVANCED

    ' Change MapMode so that SetWorldTransform works properly
    SetMapMode hdcTarget, MM_TEXT

    ' Build rotation transformation matrix
    ' In this case rotating 'rotate' degrees clockwise about point aboutX, aboutY
    myXForm = buildXForm(aboutX, aboutY, rotate)

    ' Apply the transform
    SetWorldTransform hdcTarget, myXForm

    ' Piece de resistance: bitmap gets rotated even though all we do is a normal BitBlt
    BitBlt hdcTarget, 0, 0, 200, 200, MemDC, 0, 0, vbSrcCopy

    SetWorldTransform hdcTarget, gOldWorld
    SetGraphicsMode hdcTarget, GM_COMPATIBLE
    
    ' Clean up the extra stuff we introduced
    DeleteDC MemDC

    ' Everything now back to normal, transform removed
End Sub[/blue]
 
What can I say,, Brilliant.
Thanks again for your help on this,
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top