Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
Version 2.1 uploaded today. Some patches, but new enhancements:
- Added LoadPictureGDIp.rtf file & provides more detailed info regarding loading images
- Load images from within binaries (exe, dll, ocx)
- Save image or control as rendered to GDIpImage class
- Paint image or control as rendered to an hDC
- Added ImageGroupFormat to GDIpImage class to allow testing type of group when loading images from binaries
I still need to go back & start adding more comments/remarks to the latest additions. Will do when time permits.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
FYI: New bug found. When saving to a stdPicture object as a cursor, the image comes out as black and white. I believe this is a bug related to the OLE API I use. VB exhibits this same effect when you load a cursor during design time into an image control or picturebox. I have a workaround and will apply that in the next update at end of the week. Additioinally, I'll include any other patches that may be reported between now and then.
One enhancement will be added for more advanced users. Currently, one has no way of creating a blank GDI+ bitmap, other than creating a DIB and passing it to the LoadPictureGDIplus routine. Unfortunately, if the DIB is 32bpp, the GDI+ bitmap/image will automatically be created with a format of 32bpp pARGB (pre-multiplied alpha). The added enhancement will allow you to create a bitmap of any bit depth, passing optional palette if desired, and configuring 32bpp GDI+ bitmaps as either RGB, ARGB, or pARGB. If creating a 24bpp or 32bpp bitmap, then it can be used to render to directly using the GdipGetImageGraphicsContext API. This new ability will be part of the SavePictureGDIplus function, not the LoadPictureGDIplus function. Choice made to maintain binary compatibility without adding a new function for this purpose.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
Hi,
First of all, Thanks for your work.
I'm using the abilility of your control to rotate/resize images to minimize the number of images of each product I need on my aplication, also it enabled me to use .PNG format.
Basically I use your control to show the image on distinct forms, no problem at all.
There is an exception, that is msflexgrid. It only works with StdPicture, so I use your control to generate the proper image (resized and rotated), in that case, your control has visible=false , an here apears my problem. I couldn't find how to get it with transparent color.
I've use SaveImageAsDrawnToGDIpImage function to obtain the image, as SaveControlAsDrawnToGDIpImage(True) doesn't work if control is not visible.
Any Idea ?
Attached there is an small project where i test it
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
I'll take a look, but keep this in mind... stdPicture doesn't support transparency except for GIF or Icon. This means that you'll need to save the image to stdPicture format as a GIF or Icon. Both may produce jagged edges on rotated images. GIF supports 256 colors only, icon is true color. SaveImageAsDrawn... will return image in PNG format; so this may help but with limitations noted above.
Code:
Dim tStdPic As StdPicture
Dim tAlphaImg As GDIpImage
Set tAlphaImg = AlphaImgCtl1.SaveImageAsDrawnToGDIpImage()
Set tStdPic = New StdPicture
SavePictureGDIplus tAlphaImg, tStdPic, lvicSaveAsIcon
' tStdPic now has the stdPicture (icon)
' if having issues with lvicSaveAsIcon, then try lvicSaveAsGIF
Edited: I haven't looked at your zip file; will do that later tonight when I'm home.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
Hi LaVolpe,
I got working ussign PNG format (fantastic, I got a lot better quality), I've surprised, because i thought Image control doesn't support PNG, ( maybe is only LoadPicture function).
But my problem continues, SaveImageAsDrawnToGDIpImage doesn't keep the transparent color, and SaveControlAsDrawnToGDIpImage doesn't work if control is not visible. I've tested with a visible control and SaveControlAsDrawnToGDIpImage works just perfect.
Another question, I've noticed if I resize the image to small size, and latter I try to resize to bigger size, doesn't work properly (I got diferent sizes ???), I've so set to original size first, and after that set to the desired size. Is the way it is suposed I've to go ? (on my test I use a big image, so usually I reduce the size)
Example: Original image is 20.000 width, I resize to 1.500 and latter to 10.000
Thanks in advance.
jicxicmic
Last edited by jicxicmic; Feb 23rd, 2011 at 02:32 PM.
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
SaveControlAsDrawnToGDIpImage won't work with non-visible control. This is because the control needs VB to send the Paint event to the control. VB won't do that if the control is not visible or if the control is visible but not on the screen. Without the paint event, the control has no DC to draw to since it is windowless. I've tried all I can think of to force VB to send the event, but it won't in those scenarios.
Comments about your post.
1. The image control does not support PNG. When you save the control or image to stdPicture, the returned image in the stdPicture is bitmap. But bitmap doesn't support transparency, GIF & ICO do.
2. SaveControlAsDrawnToGDIpImage does keep transparency because the image inside the returned GDIpImage class/object is PNG. However, saving the PNG to stdPicture is where you loose transparency.
Edited: Unless you also choose to include the container's background. In that case, transparency is lost because the control's container is not an alphablended bitmap.
Using your sample project, I think the workaround is to use the SAVESTRUCT. Modified your routines as follows. What do you think?
Code:
Private Sub Horizontal_Click()
Dim Cx As Long, Cy As Long
GetScaledImageSize AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 140, 140, Cx, Cy, , , False
SaveOptions.Width = Cx: SaveOptions.Height = Cy
LoadImageIntoControl
SaveOptions.Width = 0: SaveOptions.Height = 0 ' reset; will use actual size if these are zero
End Sub
Private Sub Vertical_Click()
SaveOptions.RSS.Angle = 90
SaveOptions.RotatingCanGrowImage = True
LoadImageIntoControl
SaveOptions.RSS.Angle = 0 ' reset
End Sub
Private Sub LoadImageIntoControl()
Dim tPic As StdPicture
Image1.Picture = Nothing
Set tPic = New StdPicture
If SavePictureGDIplus(AlphaImgCtl1.Picture, tPic, lvicSaveAsBitmap, SaveOptions) Then
Image1.Picture = tPic
End If
End Sub
Last edited by LaVolpe; Feb 23rd, 2011 at 06:36 PM.
Insomnia is just a byproduct of, "It can't be done"
it is just to calculate Cx and Cy ? what are 140 ? I wanted 400 twips height, how to convert ?
Vertical function does rotation but not resize, I've mixed vertical plus horizontal functions and works ok.
Code:
Private Sub Vertical_Click()
Dim Cx As Long, Cy As Long
GetScaledImageSize AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 140, 140, Cx, Cy, 90, , False
SaveOptions.Width = Cx: SaveOptions.Height = Cy
SaveOptions.RSS.Angle = 90
SaveOptions.RotatingCanGrowImage = True
LoadImageIntoControl
SaveOptions.RSS.Angle = 0 ' reset
SaveOptions.Width = 0: SaveOptions.Height = 0 ' reset; will use actual size if these are zero
End Sub
I got a good image but there is a blank area on left and bottom sides as if resized image doesn't fit the painting area. Again, how I can select the desired size ?
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
GetScaledImageSize will return the value of the width & height of the image scaled to whatever dimensions are passed. That function accepts pixels & returns pixels, in fact the entire control uses pixels only, not twips. So, I took the 140 in your example (140*14). If you want to use twips simply supply this value instead of 140: 1400\Screen.TwipsPerPixelX. That will convert twips to pixels for the control.
Edited. If you don't use GetScaledImageSize, then whatever width/height you supply in SaveOptions will result in the image being stretched to those dimensions. GetScaledImageSize is used to keep image's aspect ratio in tact.
In your example, the vertical function wasn't resizing. If you want to resize, set the SaveOptions Width & Height members to the size of the image you want, scaled or not. The RotatingCanGrowImage member works like this: If set to true and you want the image sized say 100x50, then the image will be 100x50 rotated, but the overall size of the picture may be larger to enable a 100x50 rotation. If set to False, then the overall size of the picture will be 100x50 and the image will be rotated inside that 100x50 bounding rectangle. The actual image will be smaller than 100x50. Understand? If I'm not being clear, simply try it. Set the Angle at 45 degrees and save image with and without that member set to true to visually see the difference. Don't only pay attention to the size of the returned stdPicture, notice the size of the actual image also.
When using SaveImageGDIplus, the actual size of the image or the control is not important unless the SaveOptions Width & Height are zero & in that case, then the actual size of the image, not the control, is used.
In your case, since you are hiding the control, it is only serving the purpose of containing the image, similar to a hidden VB image control. If you have further questions, please repost your sample project and include a screen shot in that zip of what the end result should look like & I can offer a suggestion or two.
Last edited by LaVolpe; Feb 25th, 2011 at 09:34 AM.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
Control updated today. See Post#122 above for reasons.
The SavePictureGDIplus function can now create a blank GDI+ bitmap. The included SavePictureGdip.RTF file describes how this is accomplished.
Edited. Updated one more time on 4 Mar 2011 with minor corrections & one minor enhancement. See 1st post for more info
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more)
UPDATED 11 MAR 2011 to fix below issues
Bug report regarding animation.
1. When the control is animating, some annoyances have been noticed and will be addressed. My initial plan for animation was to stop/pause animation when the control's visible property set to false and restart/resume when visibility returns. However....
a. When control is visible and animating, animation does stop when control's Visible property set to False. It does restart when Visible reset to True
-- This scenario does not apply if AnimateOnLoad=False. This will be fixed. Scenario must not be limited to that property, but rather the fact it is animating or not
b. When control's Visible property is set to False at design time and at runtime if AnimateOnLoad=True or animation started manually, the control will attempt to animate. It won't paint but will change frames. Got that half right but also half wrong.
c. The control has no way of knowing thru VB events that any parent/container objects it may exist in changes visibility to false. This results in the container not visible, but the control animating (not painting but changing frames).
d. The control actually doesn't even know if it is invisible on start up. The usercontrol's Show event triggers initially whether the control's Visible property is True or False. This means when control Visible=False, it will attempt to animate if AutomateOnLoad=True (not painting but changing frames)
2. The default minimal frame interval is set to 10 ms if no frame interval has been provided in the animated resource. This default is way too low and will be increased to 50-80 ms; not sure yet.
3. Matter of education vs. bug.
a) The more controls you load that are animating, the higher CPU usage goes. The faster the animation, the higher CPU usage goes. Loading a dozen or so animated gifs, all animating at ridculous fast speeds (say 10-20 ms) can eat up 80% or more CPU usage. If these were animating say 50-100 ms, cpu usage should drop to the teens or low-20s at most.
b) When control is inside a container (picturebox, frame or even the form itself), if the container is made invisible by setting its Visible property to false, the control is not notified and does not pause/stop animation. Animation continues. You should loop thru your controls in a container that becomes invisible and stop/pause animation manually. If container becomes visible again, loop true controls and start animation again as needed.
Edited for paragraph 3b. What I wrote above is a good workaround to pause/stop animation when a control's container goes invisible, since you, the coder, dictate that. To automate pause/resume due to visibility change, will take some thought. Theoretically, the control can exist in several layers deep of containers (i.e., picbox in a picbox within another picbox inside yet another picbox, etc, etc). If any of the control's containers go invisible, then animation should pause. I have an idea that does not include hard-referencing containers nor uses subclassing. If it pans out, I'll include it in the update that fixes annoyances noted above.
Another issue I've just discovered....
The AnimationFrameChanged event has a parameter called Index. That will cause problems if the AlphaImgCtl itself is an indexed control
Without being indexed, event looks like: Private Sub AlphaImgCtrl1_AnimationFrameChanged(Index As Long)
But with being indexed, event looks like: Private Sub AlphaImgCtl1_AnimationFrameChanged(Index As Integer, Index As Long)
In the latter case VB will give you an error. The simple workaround is to manually change the 2nd Index from Index to Frame or some other word besides Index. The workaround will be for v2.1.4 and earlier. When I update the control, Index will become Frame and binary compatibility will be maintained
Edited. Follow-up. I think I have all the workarounds and will post 11 Mar 2011.
1. When animating, animation pauses and resumes when visibility is toggled
2. When not visible, animation will not start. If AnimateOnLoad=True or a call to manually start animation while invisible, then animation starts when made visible
3. If any higher level container is made to be invisible, animation will pause until container becomes visible again; then it will resume
4. The default minimal frame rate if no rate is supplied by the image resource or by you, will be 75 ms. It is a constant in cAnimator class and can be modified by you if desired
Last edited by LaVolpe; Mar 11th, 2011 at 08:20 PM.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
Potential mod forthcoming.
Problem: I found myself wanting to resize a WMF image. Ok, no biggie for 99.9% of the cases. But I know that WMFs are vector graphics that can be resized without any distortion. In this case I wanted to resize a portion of the image to something like 8x without any alphablending effects or distortion. Not possible with the control's current code
Background. WMF/EMF are converted internally to PNG. This is to allow them to be rendered with special effects, rotation, mirroring and other effects that are not possible if the image is in metafile format. Resizing the image is the same as resizing a PNG in this case. That means you get good quality stretching but alphablending is used to produce the quality. The metafile, itself, is never used during resizing; whether or not it is maintained by the control. If not familiar with raster vs. vector, here is a perfect example of what I wanted but is not available with the control, as is.
Therefore, I am messing with ideas on how to use metafiles for resizing only but internally still maintained as PNG for special effect purposes. I think this will be an optional property on the usercontrol, named something like: UseVectorResizing. If used, and if ActualSize is false and only if metafile is cached by the control, then when control is resized the cached metafile will be reloaded via GDI+ to a temp image, rendered at the required size, then GDI+ temp image destroyed. This will obviously be a speed hit. Still entertaining ideas on this...
Edited: Though I realize this is a shortfall in my control, I may not be modifying after all, for this purpose. It can be handled with outside routines or even not using the control at all but using a graphics editor for this purpose. I want to avoid the control becoming a mini-graphics editing program and want to keep it just as a control; not an application. Even I need to re-evaluate my original intentions from time to time, so I don't get into the "make this thing more than what it was intended to be" mindset
Last edited by LaVolpe; Mar 19th, 2011 at 12:59 PM.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
Hi,
This project is amazing!! I have a question about animations though:
I have a png sequence that I want to load into the control as an animation. Can I do this easily, or will I need to create a single png with all the frames in a grid. It's quite a long animation, so would take a while to do!
I've had a look at the animation example, but can't see how you actually load the animations!
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
Paul, I see you have a few choices
1) convert to animated GIF. Not good choice since gifs don't support variable alpha blending your PNGs probably have
2) convert to animated PNG format. Post #53 has a link for such a utility. Never tried it though
3) convert all images to multipage TIFF (these can be animated too)
4) load all images in separate controls and create your own manual animation via a timer and hiding/showing 'frames'
5) convert to a single PNG and can easily be done with this control's MergePictureGDIplus function...
Example for #5.
a. Add 1 alpha image control to your form and 1 command button
b. Leave all default values and paste below behind your button's click event
Code:
' I'm going to assume all your PNGs are same size and named similarly
' example file name: mySeq1.png
Dim X As Long, PMS As PICTUREMERGESTRUCT
Dim sPath As String, Cx As Long
Const NrImages As Long = 8 ' change to actual number of your 'frames'
sPath = App.Path & "\" ' change to where your 'frames' are located on disk & ensure trailing slash
PMS.Pictures = NrImages ' how many images
ReDim PMS.MIS(1 To NrImages) ' array of image classes
With PMS.MIS(1) ' get first image & base overall new image off that
Set PMS.MIS(1).Picture = LoadPictureGDIplus(sPath & "mySeq1.png", False)
Cx = .Picture.Width
PMS.CanvasHeight = .Picture.Height
PMS.CanvasWidth = Cx * PMS.Pictures
End With
' if you got an error above or get one below, check your path & filename you are trying to load
For X = 2 To NrImages ' process remaining images
Set PMS.MIS(X).Picture = LoadPictureGDIplus(sPath & "mySeq" & X & ".png", False)
PMS.MIS(X).RSS.Quality = lvicNearestNeighbor ' prevnets potential alphablending on frame edges
PMS.MIS(X).Left = Cx * (X - 1) ' set offset to render to
Next
' now test what was just done....
Set AlphaImgCtl1.Picture = MergePictureGDIplus(PMS)
Erase PMS.MIS ' free up some memory; destroy loaded images
AlphaImgCtl1.Picture.SegmentImage NrImages, 1, , 50
AlphaImgCtl1.AutoSize = lvicSingleAngle ' force control to size to actual size
AlphaImgCtl1.AutoSize = lvicNoAutoSize ' remove auto-size during animation (performance reasons)
AlphaImgCtl1.Animate lvicAniCmdStart
' if it appeared find, unrem these next lines
' AlphaImgCtl1.SegmentImage 0, 0 ' unsegment
' SavePictureGDIplus AlphaImgCtl1.Picture, sPath & "AnimatedSeq.png", lvicSaveAsCurrentFormat
Note: Nice brain teaser and unfortunately, found a bug in the property page regarding segmented images (result of a previous patch). I'll have to fix that. If you opted for #5 above, you will have problems segmenting the image in the property page. You can segment it during runtime using similar code as I did above (SegmentImage method). I'll have a patch for the property page in a day or two (need to find some time to update it).
Edited: Regarding animation settings. Those can be done via code or via the property page. To show the property page for any of the controls, simply right click and select properties.
Last edited by LaVolpe; Apr 13th, 2011 at 11:17 AM.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
Hey LaVolpe,
When I put the project into my other project, LOOKS fine, but two small worries...
When I add the control to a form, the other controls get those ascending diagonal lines of doom. (But that's no big deal, I just update UC's.)
Here's the real problem...I can't add images! I get to the property pages, and I press Browse, and I get Runtime Error 2 "The common dialog box function failed during initialization."
It happens when I right click -> properties, and when I go through Custom! :x
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
1. Are you adding this control uncompiled or compiled to your project?
2. Regarding the common dialog, it is an API version not the VB6 version. What operating system are you running?
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
Recommed you compile the usercontrol project to an ocx. Then open a new project, open the components window (Ctrl+T) and look for it. It will be called 'LaVolpe's GDI+ Based Image Rendering Control'. Add it to a form and see if you have any issues. I don't own Win7, so I can't help there if that error continues, but am willing to research some guesses if that error continues.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
I mentioned in the 3rd post, page 1, that I did not write this control to be merged with other projects. I wrote it to be used as a stand-alone OCX. So either the answer is Yes, or if you want to troubleshoot it and tweak it to work inside your other project(s), have a go.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
Thanx. Let me know if you discover the reason for that initialization error. Per MSDN, it is most likely due to low memory, but I think that is their default answer for everything
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
I realized it has something to do with command dialogs of any sort in VB6. I have a hunch that it has SOMETHING to do with being on a 64bit computer. SysWOW64<->System32 and all that hogwash, probably.
EDIT:
I've also gathered that it works fine outside of the IDE. Like on your 32bppSuite. Works compiled, but not in the IDE. What is this bull?
Last edited by mOBSCENE; Apr 16th, 2011 at 11:25 AM.
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
The control itself cannot do what you are looking for. GDI+ does not support perspective transformation. It would require a custom function/class to manually transform/move pixels from source to perspective destination. One idea may be worth investigating (assuming you can't find a good GDI+ example) is to paint each vertical column of pixels from source to destination, accounting for the destination height and column width relative to the source column. Basically like filling the destination with vertical stripes, but the stripes are relative to the 'stripes' in the original image.
The rotation you are discussing can be better visualized in the following link. You'll see 2 examples: a) non-perspective, i.e., parallelogram and b) perspective, i.e., trapezoidal with distortion. GDI+ does support parallelogram via its GdipDrawImagePointsRectI API/function
Though GDI+ can perspectively warp/sheer a path, it cannot with images. Converting all image pixels to points and warping the points, then going back to re-map those points to the original bitmap will be doable, but can be time consuming (slow)
Edited yet again. Somehow the post I replied to is missing. Here is what it said
Originally Posted by Bigweld
Hi all.,
I would like to do a simple animation of a Poker card that rotates over the Y axis and then moves to a particular area of the screen (that has a backgound image).
Here is an quite good example created using Flash of what I have in mind:
I wondering if it can be modified by using some kind of custom PictureBox
Do you think that can be possible?
Actually conversion is extremely simple. The PlgBlt API used in that project is very similar to GDI+'s GdipDrawImagePointsRectI mentioned in my previous post.
Here's how to convert that project, using my image control
1. Add an AlphaImgCtl on the form
2. Search & replace everywhere, the following
... Find: Picture2.ScaleWidth Replace with: AlphaImgCtl1.Picture.Width
... Find: Picture2.ScaleHeight Replace with: AlphaImgCtl1.Picture.Height
... Find: Picture1.ScaleWidth Replace with: AlphaImgCtl1.Picture.Width
... Find: Picture1.ScaleHeight Replace with: AlphaImgCtl1.Picture.Height
3. Add this before exiting the DoRedraw routine: AlphaImgCtl1.Refresh.
Then within the DoReDraw routine, rem out or remove the following lines
4. In Form_Load event, remove any code related to the pictureboxes. You can even remove the picboxes because they won't be used.
Also add following before the line "Call DoRedraw", within that event
Code:
AlphaImgCtl1.WantPrePostEvents = True
5. Add this code to the AlphaImgCtl1_PrePaint() event
Code:
Dim hGraphics As Long
If AlphaImgCtl1.Picture.Handle Then
GdipCreateFromHDC hDC, hGraphics
If hGraphics Then
GdipDrawImagePointsRectI hGraphics, AlphaImgCtl1.Picture.Handle, ByVal VarPtr(PtList(0)), 3&, 0&, 0&, _
AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 2&, 0&, 0&, 0&
GdipDeleteGraphics hGraphics
Cancel = True
End If
End If
6. Add the following API declarations to the form and then add an image to the AlphaImgCtl and play
Code:
Private Declare Function GdipDrawImagePointsRectI Lib "gdiplus" (ByVal graphics As Long, ByVal pImage As Long, ByRef pPoints As Any, ByVal Count As Long, ByVal srcX As Long, ByVal srcY As Long, ByVal srcWidth As Long, ByVal srcHeight As Long, ByVal srcUnit As Long, ByVal imageAttributes As Long, Optional ByVal pcallback As Long = 0&, Optional ByVal callbackData As Long = 0&) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hDC As Long, hGraphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long
What the above does is take advantage of the control's ability to allow you to draw the image vs. the control drawing the image. Let me know how things worked.
Edited: The line "AlphaImgCtl1.WantPrePostEvents = True" can be toggled true or false. Setting it to false prevents that event from being called. This way you can set it to true, automate the flip/rotation via a timer, then set it back to false after automation. Just thinking out loud.
Sorry if you saw this before I last updated. I forgot to give you the most important step: #5 above.
Last edited by LaVolpe; May 18th, 2011 at 04:34 PM.
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
Here's a real simple sample
1. Start new project & on new form, add these controls
-- timer, 2 command buttons, 3 of my AlphaImgCtl controls
-- rename AlphaImgCtl2 to AlphaImgCtlFront & rename AlphaImgCtl3 to AlphaImgCtlBack
2. Load the attached card back in AlphaImgCtlBack & card front in AlphaImgCtrlFront
3. Make AlphaImgCtl1 the same size as AlphaImgCtlBack. Organize your controls so none overlap
4. Copy & paste the following code and play.
Code:
Option Explicit
Private Declare Function GdipDrawImagePointsRectI Lib "gdiplus" (ByVal graphics As Long, ByVal pImage As Long, ByRef pPoints As Any, ByVal Count As Long, ByVal srcX As Long, ByVal srcY As Long, ByVal srcWidth As Long, ByVal srcHeight As Long, ByVal srcUnit As Long, ByVal imageAttributes As Long, Optional ByVal pcallback As Long = 0&, Optional ByVal callbackData As Long = 0&) As Long
Private Declare Function GdipCreateFromHDC Lib "gdiplus" (ByVal hdc As Long, hGraphics As Long) As Long
Private Declare Function GdipDeleteGraphics Lib "GdiPlus.dll" (ByVal mGraphics As Long) As Long
Private Type POINTAPI
x As Long
y As Long
End Type
Private Const pi180 = 3.14159265358979 / 180
Private m_PtList(2) As POINTAPI
Private Sub Form_Load()
Timer1.Enabled = False
Timer1.Interval = 50 ' reduce to make flip faster
Set AlphaImgCtl1.Picture = AlphaImgCtlBack.Picture
Command1.Caption = "Flip"
Command2.Caption = "Reset"
End Sub
Private Sub AlphaImgCtl1_PrePaint(hdc As Long, Left As Long, Top As Long, Width As Long, Height As Long, HitTestRgn As Long, Cancel As Boolean)
Dim hGraphics As Long, tSourceImg As GDIpImage
If AlphaImgCtl1.Picture.Handle Then
GdipCreateFromHDC hdc, hGraphics
If hGraphics Then
' decide which to use: card front or card back
If Val(Timer1.Tag) > 90 Then Set tSourceImg = AlphaImgCtlFront.Picture Else Set tSourceImg = AlphaImgCtlBack.Picture
GdipDrawImagePointsRectI hGraphics, tSourceImg.Handle, ByVal VarPtr(m_PtList(0)), 3&, 0&, 0&, _
AlphaImgCtl1.Picture.Width, AlphaImgCtl1.Picture.Height, 2&, 0&, 0&, 0&
GdipDeleteGraphics hGraphics
Cancel = True
End If
End If
End Sub
Private Sub Command1_Click()
If Timer1.Enabled = False Then ' abort if timer already running
Timer1.Tag = "0"
AlphaImgCtl1.WantPrePostEvents = True
Timer1.Enabled = True
End If
End Sub
Private Sub Command2_Click() ' set target to card back
Set AlphaImgCtl1.Picture = AlphaImgCtlBack.Picture
End Sub
Private Sub Timer1_Timer()
Timer1.Enabled = False ' turn off for now
Dim x As Integer
Dim NewX As Long, NewY As Long
Dim SinAng1 As Double, CosAng1 As Double
Dim SinAng2 As Double, SinAng3 As Double
Dim Zoom As Double
With AlphaImgCtl1.Picture
m_PtList(0).x = -(.Width / 2)
m_PtList(0).y = -(.Height / 2)
m_PtList(1).x = .Width / 2
m_PtList(1).y = -(.Height / 2)
m_PtList(2).x = -(.Width / 2)
m_PtList(2).y = (.Height / 2)
End With
Timer1.Tag = Val(Timer1.Tag) + 20
Zoom = Tan(45 * pi180)
SinAng1 = Sin(90 * pi180)
CosAng1 = Cos(90 * pi180)
x = CInt(Timer1.Tag) ' draw card front normal, not mirrored
If x > 90 Then x = 180 - x
SinAng2 = Sin((x + 90) * pi180) * Zoom
SinAng3 = SinAng1 * Zoom
For x = 0 To 2
NewX = (m_PtList(x).x * SinAng1 + m_PtList(x).y * CosAng1) * SinAng2
NewY = (m_PtList(x).y * SinAng1 - m_PtList(x).x * CosAng1) * SinAng3
m_PtList(x).x = NewX + (AlphaImgCtl1.Picture.Width / 2)
m_PtList(x).y = NewY + (AlphaImgCtl1.Picture.Height / 2)
Next
If Timer1.Tag = "180" Then ' done rotating/flipping
AlphaImgCtl1.WantPrePostEvents = False ' disable event
Set AlphaImgCtl1.Picture = AlphaImgCtlFront.Picture ' assign to card front
Else
AlphaImgCtl1.Refresh ' update screen
Timer1.Enabled = True ' continue timer
End If
End Sub
Here are the images. Right click and "Save As" if needed
Insomnia is just a byproduct of, "It can't be done"
Re: [vb6]Alpha Image Control (PNG, AniGIFs, TIFF, & more) [11 Mar 2011]
Originally Posted by Bigweld
Hey! This is working great!!!
Thank you, very much
PS: Do you have the complete set of card images? They look awesome
No, just did a quick google using "cardback png". Found those and thought they'd be ideal cause of their high quality and shows that transparency is not an issue with the control
Insomnia is just a byproduct of, "It can't be done"
first, THANKS... and many thanks again! to you Lavolpe,
great work!!!
About thoses "Crash" you're talking about in uncompiled mode,
I'm not sure it's related, but I had a LOT of thoses...
then I started to look in the code and I found that many function DONT return any value...
some function even does:
callingfunction1() = callingfunction2()
and both of them doesn't return any value.
I've changed that, some function, I replaced with Sub and some function now return something...
and my uncompiled project didn't crash in last 5 days...
could be related... could be not...
I also have a Class for RGB Color, I thought it would be worth sharing with you
it's very simple actually:
' 32 x 1 = 32 bits
Private Type Long32
ColorValue As Long
End Type
' 4 x 8 = 32 bits
Public Type typRGBA
Red As Byte
Green As Byte
Blue As Byte
Alpha As Byte
End Type
Public Function rColorToRGBA(ByVal plngColor As Long) As typRGBA
Dim lngRGB As Long32
' Copy value to a User Defined Type
lngRGB.ColorValue = plngColor
' Now we can make a direct bitwise copy to another UDT of the same size.
LSet rColorToRGB = lngRGB
End Function
Public Function rRGBAToColor(ByRef pRgba As typRGBA) As Long
Dim lngRGB As Long32
' Copy value to a User Defined Type
LSet lngRGB = pRgba
' Now we can make a direct bitwise copy to another UDT of the same size.
rRgbToColor = lngRGB.ColorValue
End Function
I also would like to offer my help if you want, I would very much give you a web site so you can develop your work more... just tell me if you're insterested we could manage to contact each others.
oh well... did I forgot to include the BGR to RGB translation!!
since normal color are RGB
Ex.: lngColor = rgb(1,2,3)
typMyBGRA = rColorToRGB(lngColor)
result: typMyBGRA.red = 1: typMyBGRA.green =2: typMyBGRA.blue =3: typMyBGRA.alpha =0
but PNG use BGR (blue and red switched), so to translate back and forth between rgb to brg, use the following:
Public Function SknBgrToRgb(ByRef typMyBGRA As typRGBA) As typRGBA
Dim retValue As typRGBA
Thanks for the input, but I'll keep my color conversion/assignment routines. This one line toggles from BGRA to RGBA and vice versa:
Code:
newColor = (oldColor And &HFF00FF00&) Or ((oldColor And &HFF&) * &H10000) Or ((oldColor And &HFF0000) \ &H10000)
Yes it's one of the best method on the net...
a little bit slower then mine (yes I know, Bitwise operator are very fast, but direct 32 bit assignment is faster, test it if you want)
and what about my web site proposition? I really think it could be beneficial for your excellent project. I'm not asking anything in return, you'll have full control over your web page.
also... I found a bug, I'm not sure it's control related or gdi related...
it is when doing an "objImage.Render" of a PNG onto a FORM object.
when the form got his MaxButton property to FALSE.
when image is bigger then a certain size, the X position from the source is wrong and we got 1 pixel offset on the destination.
I made a project who reproduce it... where can I send it for your own analyse?
...also... I found a bug, I'm not sure it's control related or gdi related...
it is when doing an "objImage.Render" of a PNG onto a FORM object.
when the form got his MaxButton property to FALSE.
when image is bigger then a certain size, the X position from the source is wrong and we got 1 pixel offset on the destination.
I made a project who reproduce it... where can I send it for your own analyse?
I'm always interested in bug reports. Please post a sample project or code that reproduces the problem.
Edited: Note that the control defaults to centering the image in the control. If the control size changes and proportional Aspect is used, it is possible the image can be 1 pixel off depending on whether the control's bounds are even or odd. To prevent this, opt for Left alignment vs centered. Other factors may apply to like: mirroring or 180 degree rotation.
Last edited by LaVolpe; May 29th, 2011 at 11:57 AM.
Insomnia is just a byproduct of, "It can't be done"
I'm always interested in bug reports. Please post a sample project or code that reproduces the problem.
Like I said, this is a "rare" bug and hard to reproduce. posting code
might not work as the format and size of the png seem to decide if it occur or not.
I posted an exemple on a web site for you to download it. This exemple is enable to reproduce it, all comment are in the form load.
if you ENABLE the MAX button, the bug doesn't happen... (strange)
It is actually a VB-bug. I've discussed this previously. The bug is identified in post #3 (1st page) and discussed in posts #35 & #36, also on the 1st page, with the workaround. Though pictureboxes are specifically addressed, bug can apply to any VB container, i.e., the form.
Last edited by LaVolpe; May 29th, 2011 at 02:04 PM.
Insomnia is just a byproduct of, "It can't be done"