Go Back  Xtreme Visual Basic Talk > Visual Basic .NET (2002/2003/2005/2008, including Express editions) > .NET Interface and Graphics > Fuzzy gradient Lines and line smearing


Reply
 
Thread Tools Display Modes
  #1  
Old 04-08-2012, 05:28 PM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default Fuzzy gradient Lines and line smearing


I look at hundreds of VB.Net user interfaces through the internet and
they all look horribly unsophisticated from a graphics point-of-view.

Compare this to the backgrounds seen on tv broadcast
that use blurred line gradients to create
graphics that have some interesting appeal and draw the eye
to them (at least my eye).

I've attached some sample screenshot grabs below
that I have annotated with magenta rects
showing the interesting sections.

Here's my question:
What types of graphics routines can produce these types of
graphic effects?

The options that I have identified so far:
1.) More carefully done line smearing (see below..)
2.) Line drawing with a VB.Net version of the "Bresenham's line drawing algorithm"
(as passel mentions in this post) (that might allow
a specialized set anti-aliasing routines - like a wu algorithm).
3.) Line drawing with some Gaussian blurring as seen in the attachment
to this post from my Perlin Noise thread.
4.) Possibly a gradient shaped by a vector GraphicsPath?
5.) Some other VB.Net gradient generating method?
Possible the use of multiple passes with an alphafade brush?
6.) Last resort: manipulating the colors of individual pixels with lockbits marshal copying (highly undesirable).

I've done a fairly complete survey of whats out
there on the internet for VB.Net samples
for drawing lines to see if any of them
combined line drawing with gradient effects
and found very little.

I played around with some code I found that
did line drawing through mouse dragging
and managed to achieve what I call the "line smearing" effect.
I've attached my Line_Smearing_Demo below

As yet I have been unable to combine lines with shaped bezier curves,
to produce Guilloche/Lissajous/complex Spirograph patterns
like those seen on this page.

Any comment/suggestions welcome (thanks for any in advance).
Attached Images
File Type: jpg broadcast_fuzzy_gradient_lines1b.JPG (18.2 KB, 43 views)
File Type: jpg nbr_screenshot1b.JPG (21.4 KB, 39 views)
File Type: jpg broadcast_fuzzy_gradient_lines2b.JPG (17.8 KB, 36 views)
File Type: jpg nbr_screenshot2b.JPG (30.4 KB, 33 views)
Attached Files
File Type: zip Line_Smearing_Demo.zip (79.6 KB, 23 views)

Last edited by surfR2911; 04-08-2012 at 05:53 PM.
Reply With Quote
  #2  
Old 04-08-2012, 05:35 PM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default The line smearing screenshots..

The forum only allowed 5 attachments per post,
so the line smearing screenshots are attached below on this post.
Attached Images
File Type: jpg DrawLines_Screenshot1.JPG (47.5 KB, 31 views)
File Type: jpg DrawLines_Screenshot2.JPG (54.6 KB, 28 views)
Reply With Quote
  #3  
Old 04-08-2012, 07:53 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,862
Default

You didn't mention WPF.
Since the examples you linked to are done with WPF, you could always go that route.
I've played with a few VB.Net with WPF examples, and it seems pretty cool, but I don't have enough interest to set aside time for getting more familiar with it.

Most of the graphics art type stuff (my daughter does the Graphics Art for advertising for a local retail chain, and a brother in law has run his own Graphics Art related business for years, does work for the U.S. Post office (designing stamps) and a lot of other things), use much more expensive software dedicated to effects, and they both use Apple products, and most graphic art companies do.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 04-08-2012 at 07:59 PM.
Reply With Quote
  #4  
Old 04-10-2012, 04:09 AM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default WPF - yes and no..

Yes, thanks for your reply.
I didn't mention it specifically on my list but I did look at some WPF and Xaml code.

Unfortunately I didn't find any really fuzzy line routines.

You can do what is called a "soft" gradient line but it has to be drawn
veritably or horizontally and rotated otherwise the anti-aliasing isn't that good.
There is a picture on this stackoverflow page.

WPF also supports Gaussian blurring but if
ClipToBounds="True", then you get a hard boundary and if
ClipToBounds="False", then it blends down into the background instead of
blending into an opacity ramp
(an alpha mask along the edges layered separately from the
surrounding background) .

I just could not find any good examples of code that produces
lines with variable alpha masked opacity fuzziness surrounding it.

However maybe a super slim rectangle with some
per pixel opacity "splatter" might
do it - but I have found no good examples.

P.S. I do know that WPF supports alpha brushing and opacity masking, but
neither of these really produces the desired fuzziness effect.
Reply With Quote
  #5  
Old 04-10-2012, 07:54 AM
dwwolfe dwwolfe is offline
Newcomer
 
Join Date: Dec 2011
Posts: 3
Default

It looked to me like most of your samples were 16x9 screenshots. Many broadcast stations have not yet made the full transition to 16x9. What they do instead is some DirectX style 3D graphics in 16x9 and still use 4x3 or cropped 4x3 for the raw video. That way, they can broadcast 16x9 HD and still use the older 4x3 cameras in the studio and field. The gradient tinting you had highlighted was mostly on the screen edge. Someone with an older 4x3 TV would not see this unless they letterbox the broadcast image.

That being said, I have also been somewhat disappointed with user interfaces over the years. Many programmers don't spend much time on the GUI part of their program. Game developers (for obvious reasons) tend to spent much more time on graphics, but for other apps, not so much.

Sometimes, the easiest solution may be the best. Get someone (or yourself) to design a nice gradient background image (or several) with Gaussian line blur for your GUI. Then, just change the background image on your forms. This is called a "skin" or "theme" in GUI terms. If you have several (or allow users to add their own), It easily adds to function without adding much overhead. Look at the number of "skins" available for programs like iTunes, WinAmp, or other media players.
Reply With Quote
  #6  
Old 04-11-2012, 04:36 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,862
Default

Well, I've put off replying to this thread because the thought it causes me to sigh.
There are so many ways to go about doing these types of things, that I don't really want to think about it.
As has already been mentioned, you have graphic tools dedicated to help create these type of effects.
You have things like Paint.Net which allows some graphic blending and using various gradients in various ways, and levels.
Since it was a student project, it is not as evolved as something like gimp, or the many other professional tools out there, but I assume from the name that .Net code may have been involved in creating it.

A lot of the effects are gradient related, so perhaps exploring gradient manipulation would be a place to start.
The Gradients made easy project may be a nice tool to explore gradients with. I don't know, haven't downloaded it, as I don't have a need to explore what all can be done with the various forms of gradients. There are so many things that can be played with, I just don't have the desire needed to explore.

We used some gradients in the ovoid thread, and you wrote code to allow manipulating some aspects, so it seems like you have the tools to try some exploration. Perhaps the "Gradients made easy" app will aid in making that exploration faster.

But, to address one possible effect that you've identified in your original post, the fuzzy/blurred line, the effect may not be a line at all. If you used a linear gradient brush to fill an area, and you set the gradient so that it rises and falls, then you can get the appearance of a bright line down the middle of a blurred area perpendicular to the direction of the gradient.

What I mean is, you define a linear gradient using two points, so those two points define a line, and the color components of the pixels that make up that line will change to map the complete gradient curve along the length of that line.
So, that sets the length of the gradient cycle (the length of the line), and the orientation of the gradient (the slope of the line).

When you fill an area with the linear gradient, if the length of the gradient line is longer than will fit in the dimension of what you are filling, then you will see only part of the gradient.
If the length of the gradient line is shorter than the dimension you are filling, you will see the gradient repeat until it hits the border of the dimensioned being filled.

If the two points defining the linear are not parallel to an axis (X, Y) (i.e. a diagonal line), then the fill with be diagonal.

Now, if we define a horizontal linear gradient, which goes from low alpha, to high alpha, and back to low alpha (say using a triangular blend), then you will have a line that is "bright" in the center and faded out to either side.
If you then use that horizontal gradient (let's say it is defined as being 40 pixels long) and use it to fill a vertical rectangle, 40 pixels wide, by any vertical height we want, then what it looks like is a bright vertical, horizontally blurred line.

Quick example: Paste this in a new project.
Code:
Imports System.Drawing.Drawing2D

Public Class Form1
  Dim termpoint As New Point(573, 353)
  Dim centerColor As Color = Color.FromArgb(192, 128, 255, 255)
  Dim edgeColor As Color = Color.FromArgb(0, 0, 0, 0)

  Private Sub FillGradient(ByVal gr As Graphics, ByVal _
    point1 As Point, ByVal point2 As Point, ByVal color1 As  _
    Color, ByVal color2 As Color, ByVal line_width As _
    Single)

    If point1 <> point2 Then
      Dim the_brush As New LinearGradientBrush( _
          point1, point2, color1, color2)
      the_brush.SetBlendTriangularShape(0.5F, 1.0F)
      gr.FillRectangle(the_brush, Me.ClientRectangle)
      gr.DrawEllipse(Pens.Yellow, 200 - 10, 200 - 10, 20, 20)
      the_brush.Dispose()
    End If
  End Sub

  Private Sub Form1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
    If e.Button = Windows.Forms.MouseButtons.Left Then
      termpoint = e.Location
      Me.Invalidate()
    End If
  End Sub

  Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    FillGradient(e.Graphics, New Point(200, 200), termpoint, edgeColor, centerColor, 20)
  End Sub

  Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Me.BackColor = Color.Black
    Me.DoubleBuffered = True
  End Sub
End Class
Drag the mouse around. The circle indicates the First point of the gradient. The mouse position when dragging, is the second point.
The form is filled with the resulting linear brush.
When the mouse is horizontally level with the circle, creating a horizontal linear gradient, then you have vertical looking fuzzy lines as the horizontal linear gradient is "stacked" to fill the area.
The closer to the circle you are, the shorter the gradient line, so the gradient curve is applied to a smaller line of pixels.
As you drag the mouse to a position off axis compared to the circle, you have slanted "fuzzy lines".
So, you should be able to create lines, similar to the lines you identified by simply creating a linear brush the width you want, translate out to where you want the line to start, rotate to the angle you want the line to go, then fill a rectangle with the linear brush, giving you the fuzzy line from one point to another.

Fading the endpoints of those lines, is another issue, and I don't think can be easily handled with the capability of the Drawing2D class. WPF has opacity masks, which can be used to alter the alpha of an area of a bitmap, convenient.

Since I don't want to spend a lot of time on this, I did put together a quick example, which does the single line, as I mentioned above (mouse drag on the picturebox to move one end of the line).
It also draws a few circular pathGradients (has to be a closed figure, won't do lines) to sort of simulate a couple of the other things. Nothing too involved.
Unfortunately, since I'm not spending the time, there are little to no comments.
If you download Mike Hankey's gradient demo and source from the link above, hopefully he has taken the time to explain this stuff in much more detail than I have any desire to (still haven't checked it out for myself, so I can't say).

As for generating the various patterns (spirograph, Lissajous), I guess I would look at the code to see what the logic is behind it and see it I could replicate it.
The various circle rotating around circle or inside circle stuff (e.g. spirograph), could fairly easily be done with matrix manipulations, but I don't know if that is what their code would boil down to.
If using transforms, I wouldn't be using Bezier curves, so the Bezier curve methods would probably be more efficient then simple matrix transforms.
Lissajous patterns are also usually a fairly easy thing to do since it just involves applying two sine waves at different phases ( i.e. sine vs. cosine, or anything in between) and/or frequencies and/or amplitudes.
One wave determines the X coordinate, and the other the Y coordinate.
One of Bob Powell’s examples, demonstrating the "long persistent scope fade", uses lissajous pattern as his medium. I haven't downloaded the project to see how he does the drawing, perhaps I should.

I do have code picked up from somewhere that manually calculates the points of a Bezier curve.
I tested it, out of curiosity, back when you started the ovoid thread, to see if given the same control points and tension, if it drew the same curve as the Drawing2D class, and it pretty much looked like it did to me.
But I didn't make use of it for any reason, since I just took the route of manually adjusting angle and radius delta to make the ovoids drawn in concentric circles tangent.
I didn't want to try to figure a way to programmatically figure that out using manual Bezier curve point calculations.

Seems like there may have been something else I wanted to say, but I can't think of it now, so will post this as is.

P.S. I think I remember what it was. In the example attached, there are various three "line" drawing routines. You can comment out the one currently used, and uncomment another to try it out.
The first, is the straight forward, just draw the line end to end.
The second, I believe, used a pathgradient, but could never give quite the same result as the linear brush. The way it was left, isn't trying to emulate the line, just doing something like a fading strip with a twist in the middle. If you play around with all the various possibilities, all kinds of things can show up, which could be useful in one way or another, I don't know.
I just left it in, not trying to do anything specific.
The third, which should one uncommented in the zip, uses a different paradigm. Rather than fill a rotated rectangle with the linearGradientBrush directly in the picturebox, it renders it in a bitmap (which created bitmap backgrounds are transparent because the bitmap is filled with zeros).
This allows the code to manually (not in an efficient manner), re-adjust the Alpha of the last 80 rows of pixels to fade the line out toward the end.
A simple fixed lowering of the alpha over the 80 rows does fade it, but because it is not gama corrected across the gradient, the fade appears to sharpen the line into a spear point.
But, I am not going to take the time to figure out how to gama correct the gradient adjustment, or make the alpha adjustment more effcient. It is, what it is, a quick example of possibilities, and a possible starting point for something better.
Attached Files
File Type: zip Gradient_Test_1.zip (84.0 KB, 9 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 04-11-2012 at 05:10 PM.
Reply With Quote
  #7  
Old 04-12-2012, 06:26 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,862
Default

Since I mentioned in the previous post (double posting again), that there are many ways to approach this, I should at least provide one example of a different approach to back up that assertion.

This small example is based on Bob Powells example of a way of doing drop shadow or Text Halo Effect (Link to Text Halo Effect, link to soft shadow included).
The method doesn't depending on using a gradient.
It takes advantage of the interpolation mode of the DrawImage method to smooth the edges and blend colors when expanding a bitmap to fill an area.
The technique is relatively simple.
You draw your lines (or text in his case), scaled down some number of times, so you have a small version of your graphic (in my case, I'm scalling it down to 1/7th of the orignal size).
Then when you scale that image back up to full size, the lines are expanded and edges blended using the InterpolationMode selected.
You would then normally, draw the original lines on top of the "fuzzy" lines.
To be clear, you have to draw the lines in the small scale on the small bitmap, then DrawImage the small bitmap (with scaling) back up to full size.
Unfortuanately, you can't draw the image fullscale, then use drawimage with scalling to shrink it down onto a small bitmap, then use drawimage to scale it back up to full size, and get the interpolation smoothing effect. I'm not sure why. I thought that would be convenient, just draw the image full size, shrink it down (loosing some pixels in the process), then expanded it back out (having to interpolate to replace the pixels lost), but it didn't work.
The image expanded back out to exactly what it was before it was shrunk, so some caching of the original image must be going on, and it is just being rendered small from that image, so when you expand it, it expands it from the cache, not the small rendered image. There might be a way to force it to work, but I didn't pursue it, since drawing on the small bitmap does what is expected.

In this particular case, if I wanted to draw lines freehand, and wanted the fullscale lines on top of the "fuzzy", I should use a transparent bitmap to collect the fullsize drawing.
The miniture drawing is done in a small transparent bitmap.
But, since I'm using a BufferedGraphics object for the fullsize drawing, I can't render that overtop of the fuzzy background, it would wipe it out.
So, I have to render the fullsize line drawing first, then put the fuzzy on top, so it does murk-up the lines a bit, especially if you draw patterns on patterns.
The code could be easily changed to use two bitmaps, rather than a BufferedGraphics object so that the full size drawing of lines could be layered on top of the fuzzy layer.

Of course, you could also just not draw the full size line drawing, so you only draw the fuzzy part, as a texture type path (although not using actually GraphicPaths here).

Anyway, just another quick example, no comments in the code. The Right mouse button, when clicked in the picturebox will cycle through four pens. I originally had only the one yellow pen, then added the red,green and blue before posting.
A bit simplistic. Dragging on the picturebox will draw a continuous line with the currently selected pen.
Button 1 will clear the drawing, and button 2 will draw a canned pattern of circles and a rectangle as an example that programatically drawn lines look smoother than hand drawn lines, so don't judge the effect just by the freehand drawing.

P.S. Meant to mention that I also made some changes to "increase" the size of the fuzziness (compared to Bob's code), by drawing fatter lines in the small bitmap.
So, I'm multiplying the fuzzsize by 3 in the pen definitions.
An interesting thing to try, is to reverse the fuzzSize value and the Pen size multiplier.
At the top of the code, change the fuzzSize from 7 to 3, and change the pen multipliers from 3 to 7.
The hand drawn lines, will look much rougher with this, with quite visible gappiness in the fuzz, but the fuzz drawn by code, (lines and ellipses) will be smoother than in the original (7,3) case. Interesting.
Attached Files
File Type: zip FuzzyDraw.zip (16.2 KB, 12 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 04-12-2012 at 06:40 PM.
Reply With Quote
  #8  
Old 04-13-2012, 07:45 AM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default blurred lines and moving toward per pixel alpha masking

Quote:
That being said, I have also been somewhat disappointed with user interfaces over the years. Many programmers don't spend much time on the GUI part of their program. Game developers (for obvious reasons) tend to spent much more time on graphics, but for other apps, not so much.
We are in totally agreement and I wish there were more coders on the forum that think like you do.

Quote:
Sometimes, the easiest solution may be the best. Get someone (or yourself) to design a nice gradient background image (or several) with Gaussian line blur for your GUI. Then, just change the background image on your forms. This is called a "skin" or "theme" in GUI terms.
I know about skinning and have used this approach with VB6 programs but .Net has supposedly better (or at least expanded) graphics functions and I'm determined to explore them before I give up and go back to the old design-time pre-generated graphics approach.

Quote:
A lot of the effects are gradient related, so perhaps exploring gradient manipulation would be a place to start.
Been there, done that.
Quote:
The form is filled with the resulting linear brush.
I looked at your "Gradient_Test_1.zip" - this is not close to the effect shown in my posted pictures at all even (even with endpoints fading). Sorry.

Quote:
so the Bezier curve methods would probably be more efficient then simple matrix transforms.
Hopefully you saw this post:
"Beziers adjustable at runtime by drag handles"

Quote:
I do have code picked up from somewhere that manually calculates the points of a Bezier curve.
I tested it, out of curiosity, back when you started the ovoid thread, to see if given the same control points and tension, if it drew the same curve as the Drawing2D class, and it pretty much looked like it did to me.
But I didn't make use of it for any reason, since I just took the route of manually adjusting angle and radius delta to make the ovoids drawn in concentric circles tangent.
I didn't want to try to figure a way to programmatically figure that out using manual Bezier curve point calculations.
Code that manually calculates the points of a Bezier curve in VB.Net. Please free to post.
I was looking at "GraphicsPath.GetPathPoints methods" to get these points but if you have a better way..

By the way - I'm working on combining Beziers with other path types.
There is a PathPointType enumeration involved - have you ever seen any VB.Net code that enumerates these numerical values. It may come in handy for path intersection hit testing with segment dissection (isolation).

Quote:
Since I mentioned in the previous post (double posting again), that there are many ways to approach this, I should at least provide one example of a different approach to back up that assertion.
Please feel free to double post all you want - much appreciated!

Quote:
It takes advantage of the interpolation mode of the DrawImage method to smooth the edges and blend colors when expanding a bitmap to fill an area.
The technique is relatively simple.
Meant to mention that I also made some changes to "increase" the size of the fuzziness (compared to Bob's code), by drawing fatter lines in the small bitmap.
So, I'm multiplying the fuzzsize by 3 in the pen definitions.
An interesting thing to try, is to reverse the fuzzSize value and the Pen size multiplier.
At the top of the code, change the fuzzSize from 7 to 3, and change the pen multipliers from 3 to 7.
The hand drawn lines, will look much rougher with this, with quite visible gappiness in the fuzz, but the fuzz drawn by code, (lines and ellipses) will be smoother than in the original (7,3) case. Interesting.
Yes, I played around with it. I could see it making a nice drop shadow, but it's still not quite there in terms of the effect shown in the pictures above.

In terms of curve drawings check out these vbHelper pages::
drawing chrysanthemum_curves, drawing butterfly curves
..of course neither uses the anti-aliasing smoothing interpolation that your second attachment uses, but there is a sample of that also.

I'm aware that WPF has an OpacityMask and that WPF has the power of DirectX hardware acceleration behind it, but the thing is that there is no directx sdk anymore - it's now inside the windows sdk, so windows itself is hardware acclerated at the operating system level, it's just so frustrating that the .Net framework System.Drawing.Drawing2D is not.

But you shouldn't need either WPF or DirectX to make this effect happen.

It's like trying to thread a needle with a sledge hammer - really we just need to manipulate less than a thousand pixels at most. I really think there has to be a software solution that doesn't require massive hardware help from an expensive video card.

I'm also disappointed that basically every other language but VB.Net has a Bresenham, Wu, and DDA (Digital Differential Analyzer) anti-aliasing examples but VB.Net doesn't have even one working example.
VB6: Bresenham code, Wu Code, Dana Seaman Anti-aliasing example
Here is supposedly some Bresenham code, but without any pixel plotting (SetPixel, LockBits) it doesn't actually draw anything.

I think the only approach that is going to have a reasonable chance of duplicating the effects shown in the pictures of my first post is to build a pixel analyzer and alpha map generator.

Take an unvaried blue background (with some subtle of blue gradients thrown in at design time), then analyze how white shifted the pixels are the final picture and generate a greyscale alpha map, that when blended with a rectangle of solid white pixels can produce the necessary color shifting overlay.
Hopefully this can be done with a texturebrush but if it comes down to using locking an unlocking of individual pixels then so be it.

I've looked around for such an alpha mask generator and really found none with Vb.Net code.

Combining a greyscale alphamask image with a full color image -the closest vb.net code I could find is the create 3d anaglyph code where the greyscale "DepthMap" is combined with the actual picture to create a different final result (I know its not really the code I need but at least it uses lock bits instead of adjusting alpha using set pixel).
If only this code could handle more than rects and ellipses.
I found this code interesting though. Of course color matrices can set alpha values.

Quote:
Originally Posted by passel
Well, I've put off replying to this thread because the thought it causes me to sigh.
I feel the same way because I know that .Net .Drawing2D has no built in "big" noise functions (Perlin, Worley, or Simplex) and that localized "little noise" functions (like a splatter-blur function) don't exist at all. I remember Gavin0's crude VB6 line smudge code but VB.Net has nothing like that and a sophisticated approach to carefully crafted ARGB per pixel color manipulation will probably be required.

Last edited by surfR2911; 04-13-2012 at 09:08 AM.
Reply With Quote
  #9  
Old 04-14-2012, 03:54 AM
PlausiblyDamp's Avatar
PlausiblyDamp PlausiblyDamp is offline
Ultimate Contributor

Forum Leader
* Expert *
 
Join Date: Nov 2003
Location: Newport, Wales
Posts: 1,812
Default

Quote:
But you shouldn't need either WPF or DirectX to make this effect happen.

It's like trying to thread a needle with a sledge hammer - really we just need to manipulate less than a thousand pixels at most. I really think there has to be a software solution that doesn't require massive hardware help from an expensive video card.
It is more a case of the best tool for the job, the way windows works (and as a result winforms) was pretty much designed about 20+ years ago and built with the hardware of the time in mind. It was never really designed for the very graphics rich applications people expect these days.

WPF was designed to take advantage of newer hardware and to remove some of the limitations of how drawing in a traditional windows application works. http://msdn.microsoft.com/en-us/library/ms742196.aspx gives the realistic hardware levels and a DirectX 9 compatible video card is pretty much standard on any pc bought in the past few years. If that is an issue dropping back to .Net 3 only requires a DirectX 7 capable card for hardware accelerated rendering, you certainly don't need to spend a fortune on a video card to get a decent level of hardware acceleration (£20 will get a DirectX 10 card these days).
__________________
Intellectuals solve problems; geniuses prevent them.
-- Albert Einstein

Posting Guidelines Forum Rules Use the code tags
Reply With Quote
  #10  
Old 04-14-2012, 05:56 AM
AtmaWeapon's Avatar
AtmaWeapon AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,505
Default

For a lot of this stuff, you'll likely spend 1 hour in WPF for every 3-4 you'd spend in Windows Forms. For the rest of it, there are dedicated special effects software programs where you will spend 5 minutes for every hour of WPF.

It's only worth using WinForms and even WPF for animated effects like your examples if you're doing it for exploration or fun. It's a very niche topic, and you'll find more papers than tutorials on the various issues.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #11  
Old 04-14-2012, 06:00 PM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default WPF Feedback

Thanks to PlausiblyDamp and AtmaWeapon,
for their advice, but I have decided to go the non-WPF route.

I want to learn the full extent of what
System.Drawing.Drawing2D Namespace can do,
so I will take whatever time is needed.

Plus --even though I fooled around with
GDIPlus in VB6, using OnErr0r's typelib,
and GDIPlus using C++.Net,
I still don't know how to be totally fluent
in GDIPlus with VB.Net.

There is much to be explored and
hopefully by the end of my exploration I will
know most, if not all, the ways to do manipulations
of individual pixels in VB.Net without WPF
(no matter how "niche" the topic).
Reply With Quote
  #12  
Old 04-15-2012, 01:18 AM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,862
Default

Quote:
Originally Posted by surfR2911 View Post
...I looked at your "Gradient_Test_1.zip" - this is not close to the effect shown in my posted pictures at all even (even with endpoints fading). Sorry.
...
Well, there are dozens of effects, and I didn't try to emulate all of them.
Mostly, it was just the one, and perhaps you didn't recognize it in a new context.
I just chose to emulate one line effect. Attached is your original picture with the line I'm drawing on it. It is the one outside the magenta box.
I felt like it was similar to one of the first two lines inside your magenta box.

As for locking to update the alpha, the purpose here was just to demonstate one method of doing that one effect, so using setpixel was fast enough for one line. You can always optimize it. There is no big magic to using lockbits, but I'll show the code for implementing the same loop, using two ways of using lockbits.
Code:
    'Since the line is drawn horizontally and rotated to the angle we want,
    'to fade the end of the line along its length, we adjust the alpha 
    'of the last 80 columns of the line down by a percentage per column of pixels.

    'Dim clr As Color
    'Dim alpha As Single
    'If lngth > 80 Then
    '  For L As Integer = lngth - 80 To lngth - 1
    '    alpha = ((lngth - L) / 80)
    '    For w As Integer = 0 To bmp.Height - 1
    '      clr = bmp.GetPixel(L, w)
    '      clr = Color.FromArgb(alpha * clr.A, clr)
    '      bmp.SetPixel(L, w, clr)
    '    Next
    '  Next
    'End If


    'Dim alpha As Single
    'Dim alphaByte As Byte
    'Dim abp As Integer  'alpha byte pointer
    'Dim abpStep As Integer 'Step between rows.
    'If lngth > 80 Then
    '  Dim fadeRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
    '  Dim bmd As BitmapData = bmp.LockBits(fadeRect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
    '  abpStep = bmd.Stride
    '  For L As Integer = lngth - 80 To lngth - 1
    '    abp = L * 4 + 3                    'get the alpha byte offset for the top pixel in the column of pixels
    '    alpha = ((lngth - L) / 80)         'Determine the scaling factor we want to reduce this column of alpha values by
    '    For w As Integer = 0 To bmd.Height - 1          'for each pixel in the column
    '      alphaByte = Marshal.ReadByte(bmd.Scan0, abp)  '  read the alpha byte
    '      alphaByte = CByte(CSng(alphaByte) * alpha)    '  scale the alpha byte down
    '      Marshal.WriteByte(bmd.Scan0, abp, alphaByte)  '  write the alpha byte back
    '      abp += abpStep                                '  increment the alpha byte pointer to point next alpha byte below
    '    Next
    '  Next
    '  bmp.UnlockBits(bmd)
    'End If

    Dim alpha As Single
    Dim abp As Integer  'alpha byte pointer
    Dim abpStep As Integer 'Step between rows.
    If lngth > 80 Then
      Dim fadeRect As New Rectangle(0, 0, bmp.Width, bmp.Height)
      Dim bmd As BitmapData = bmp.LockBits(fadeRect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb)
      Dim bytes(bmd.Stride * bmd.Height - 1) As Byte
      Marshal.Copy(bmd.Scan0, bytes, 0, bytes.Length)
      abpStep = bmd.Stride
      For L As Integer = lngth - 80 To lngth - 1
        abp = L * 4 + 3                    'get the alpha byte offset for the top pixel in the column of pixels
        alpha = ((lngth - L) / 80)         'Determine the scaling factor we want to reduce this column of alpha values by
        For w As Integer = 0 To bmd.Height - 1          'for each pixel in the column
          bytes(abp) = CByte(CSng(bytes(abp)) * alpha)   '  scale the alpha byte down
          abp += abpStep                                '  increment the alpha byte pointer to point next alpha byte below
        Next
      Next
      Marshal.Copy(bytes, 0, bmd.Scan0, bytes.Length)
      bmp.UnlockBits(bmd)
    End If
Quote:
...of course neither uses the anti-aliasing smoothing interpolation that your second attachment uses, but there is a sample of that also.
No, that just set the anti-alising drawing mode, so shows anti-aliasing effect on line drawing. There is no interpolation mode, which only applies when images are rescaled.

Quote:
I'm aware that WPF has an OpacityMask and that WPF has the power of DirectX hardware acceleration behind it, but the thing is that there is no directx sdk anymore - it's now inside the windows sdk, so windows itself is hardware acclerated at the operating system level, it's just so frustrating that the .Net framework System.Drawing.Drawing2D is not.
The Windows hardware acceleration you speak of came about with Vista in 2006.
And in 2006, in concert with that capability, they released the .Net 3.0 framework so that developers could take advantage of that capability. The .Net 3.0 framework provided several new classes, one of which provided the Visual Studio IDE a completely new Form class, where you can drag buttons, and panels, and labels, and drawing areas. It added new 3D capability as well as 2D capability and used the hardware accelerated capabilities that you're missing.
The new class was called WPF for short.

The older System.Drawing.Drawing2D is an old class, that provided some managed wrappers, to access some (not nearly all) of the capabilities of GDI+.
GDI+ is no more "managed" code than GDI is. GDI+ is just a newer class than GDI that extends the graphics capability of Windows to manipulate ARGB formatted bitmaps.
Six years later, when hardware accelarated drawing made its way into the Windows GUI, then a newer class again was created to take advantage of that.

Quote:
...
It's like trying to thread a needle with a sledge hammer - really we just need to manipulate less than a thousand pixels at most.
Well, I don't know if less than a thousand pixels would be true in most cases, at least the ones you're proposed.
Just fading the last 80 pixels of the line I've drawn, with the glow of 10 pixels on each side in the scaled down picture attached to this post means processing 1600 pixels.
The one in the previously attached code was a bigger line (assumed your attached jpgs were scaled down and the image was originally larger, so I made the line and glow to a larger scale.
That glow area was 40 pixels across, so that small area involved 3200 pixels.
I'm not saying you can't do some neat processing within the bounds of Drawing2D, but less than a 1000 pixels is not much area of screen (less than 1/1000ths on most, I would assume).

Quote:
I'm also disappointed that basically every other language but VB.Net has a Bresenham, Wu, and DDA (Digital Differential Analyzer) anti-aliasing examples but VB.Net doesn't have even one working example.
DrawLine is going to be using Bresenham, and anti-aliasing is also included if you set the mode, so there isn't much reason to have an example of doing it manually in VB.Net since you already have the algorithm shown in any number of languages. If you need to implement the algorithm to modify an array of bytes representing an image, then you already have all the parts needed in various examples to put that together.
If no one else feels the need for it, then no one is going to produce an example of all algorithms in every new language that pops up.
You've already posted an example of implementing Bresenham's line drawing in VB6 using PSet. A process that is a thousand times slower than using the built-in Line statement.
If you feel that there should be an equally useless example implemented in .Net, just to illustate the algorithm, I say why? There are plenty of useless examples already to demonstrate the method. When there is a practical reason to use it, then there will be a practical example of using it.
Attached Images
File Type: jpg SingleFuzzLineExample.jpg (68.7 KB, 13 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 04-15-2012 at 01:27 AM.
Reply With Quote
  #13  
Old 04-15-2012, 09:45 PM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default New lockbits code and etc.

I liked the lockbits code.
This is very much closer to the initial picture that I posted.
I think lockbits combine with more sophisticated alphamasking will
allow the right level of irregular splatter blurring to create many effects
for which there are few VB.Net WinForms code samples at present.
Quote:
It added new 3D capability as well as 2D capability and used the hardware accelerated capabilities that you're missing. The new class was called WPF for short.
Actually the hardware acceleration is secondary to achieving exactly the right type of per pixel alpha manipulation in WinForms --I'm not ready to go WPF just yet.
Quote:
GDI+ is just a newer class than GDI that extends the graphics capability of Windows to manipulate ARGB formatted bitmaps.
Yes, I know, but I haven't fully explored this yet.
Quote:
That glow area was 40 pixels across, so that small area involved 3200 pixels.
I'm not saying you can't do some neat processing within the bounds of Drawing2D, but less than a 1000 pixels is not much area of screen (less than 1/1000ths on most, I would assume).
On my iCore7, overclocked above 4.0Ghz your lockbits code has quite an acceptable speed for the extra 2200 pixels.
Quote:
DrawLine is going to be using Bresenham, and anti-aliasing is also included if you set the mode, so there isn't much reason to have an example of doing it manually in VB.Net since you already have the algorithm shown in any number of languages.
I want to be able to play with the anti-aliasing - not just play around with setting certain smoothing and interpolation modes.
I want explore custom anti-aliasing modes (combined with using noise that can be shaped for procedural textures).
Quote:
You've already posted an example of implementing Bresenham's line drawing in VB6 using PSet.
If you feel that there should be an equally useless example implemented in .Net..
Not useless at all!
I'm still learning how to be "adaptive" from VB6 to VB.Net.
Comparing and contrasting - doing the Rosetta Stone thing.
It's what I need to be able to "flip" code in my head between these two very different languages.

Hopefully you (passel) will have a chance to check out
"beziers_segments2_with_pathfill.zip", which I just posted.
Just one more step toward a whole new variety of drag morph-able "smart" shapes.

Last edited by surfR2911; 04-15-2012 at 10:10 PM.
Reply With Quote
  #14  
Old 04-18-2012, 06:00 AM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default lockbits - more research

jo0ls - bug when locking a portion of a 32bpp bitmap.
Workaround - If the bitmap is 32bppARGB then specify 32bppRGB for lockbits -psc code

Remember the Scan0-Stride diagram from Bob Powell's LockBits article,
well I found something similar at the bottom of this WayBack Machine article:
"Basic Image Processing support in C#"
(there are also links to Nand-ing and Or-ing bits pages with helpful images)

Lockbits - Inadequate handling of edge pixels causes streaking (off forum thread with some interesting blurring pics)

FastPix (LockBits wrapper) - by Vic Joseph(boops boops)

Alphamask code using FastPix wrapper

Re: Bresenham texture mapping (off forum thread):
Quote:
It works by dividing up a quad (4 sided polygon) into a number of scanlines. These are horizontal lines of pixels, together making up the quad.
Each scanline needs a pixel color look-up from the source texture, in order for the pixels to be rendered the correct colour.
A source scanline, which wouldn't be horizontal (most likely) needs to be iterated along, as we go along the scanline to be rendered.
So we need to iterate along 2 lines simultaneously, one is the destination scanline, that makes up the quad to be rendered, the other is the source scanline which is where we get the pixel colors to texture map the quad.
The Bresenham algorithm iterates along a line, but the difficulty lies in synchronizing it with the iteration of the other line at the same time since both lines will very rarely (if ever) be the same length. To make things more annoying the source scanline should really be defined with floating point accuracy, in order to get a good final image (and must have sub-pixel accuracy if we want to add any kind of decent filtering method later down the line).
wossname seems to have solution but no code is shown in last post of thread

"Fast Pointerless Image Processing in .NET (C#.Net)"
VB.Net function for making a Pinned Array from a bitmap:
Code:
Imports System.Runtime.InteropServices 'Above class declaration
	Public Function CreatePinnedArray(ByRef bmp As Bitmap) As Integer()
		Dim pixelData(bmp.Width * bmp.Height - 1) As Integer
		GCHandle.Alloc(pixelData, GCHandleType.Pinned)
		bmp = New Bitmap(bmp.Width, bmp.Height, bmp.Width * 4, _
		   Imaging.PixelFormat.Format32bppArgb, _
		   Marshal.UnsafeAddrOfPinnedArrayElement(pixelData, 0))
		Using g As Graphics = Graphics.FromImage(bmp)
			g.DrawImageUnscaled(bmp, New Rectangle(0, 0, bmp.Width, bmp.Height))
		End Using
		Return pixelData
	End Function
I knew C# could marshal unsafely but I didn't think
VB.Net had access to something like a a Marshal.UnsafeAddrOfPinnedArrayElement method.

It would be nice if I could convert "Per Pixel Alpha Blend in C#" to VB.Net..

Finally, just to throw a bone for the WPF crowd,
here's a link to some opacity mask code:
"Use Transforms and Opacity Masks to Create a Reflection in WPF/E"

Last edited by surfR2911; 04-18-2012 at 06:30 AM.
Reply With Quote
  #15  
Old 04-18-2012, 09:41 AM
AtmaWeapon's Avatar
AtmaWeapon AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,505
Default

I'm just poking my head in for an aside, but it's an important one.

Every time I see DrawImageUnscaled() I cringe. It sounds like the right tool for the job. "Unscaled" implies that it skips expensive scaling steps that the other methods do. Methods like this are why I strongly recommend spending free time reading random documentation that looks interesting. Have a read of the documentation or just peek at the good parts here:
Quote:
An Image stores a value for pixel width and a value for horizontal resolution (dots per inch). The physical width, measured in inches, of an image is the pixel width divided by the horizontal resolution. [...]

The DrawImageUnscaled method draws an image using its physical size, so the image will have its correct size in inches regardless of the resolution (dots per inch) of the display device. [...]
Normally, when you draw an image, you'd expect a bigger display with a higher resolution to show the image smaller. Sometimes, the physical dimensions matter, and you'd like a 1-inch square image to be 1-inch square no matter what device it's displayed on. DrawImageUnscaled() is the tool for that job. Ironically, that means quite often the image must be scaled!

The documentation implies that a lot of work has to be done to draw the image this way. First, the original resolution of the image needs to be fetched. Then, the current display resolution needs to be fetched. Then, the correct device width and height must be calculated. Then, the image must be scaled. Finally, it can be drawn, at a size you might not expect (especially considering how, in the near future, a mostly homogenous display resolution of 96 DPI won't be a guarantee.)

The only reason I can figure why DrawImageUnscaled() can actually scale is because the designers hoped people would see DrawImage() and think, "Oh, this one has the simplest name, therefore is intended to be the easiest, no-brainer solution to drawing an image. I'll look at the others when I have complex needs." Unfortunately, this isn't true. People tend to skip right over it as soon as they see "Unscaled" and assume "Oh, this must be the simplest no-brainer call to draw an image. Why else would they give it a special name?"

Always read the documentation. Or you won't know what your code is doing
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #16  
Old 04-18-2012, 12:45 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,862
Default

Quote:
Originally Posted by surfR2911 View Post
...It would be nice if I could convert "Per Pixel Alpha Blend in C#" to VB.Net..
It probably wouldn't be too hard to port, although it seems to be something you've been wanting to avoid.

The C# code is just using InteropServices to access good old GDI and user32 dlls to access the DCs and the UpdateLayeredWindow call that you've seen demonstrated any number of times in VB6.

I'm not sure why it is called Per Pixel Alpha Blending, since it never accesses the individual pixels in the code directly. But I suppose the UpdateLayeredWindow call is essentially doing that for you.

In .Net, if all you wanted was to shape the form and control opacity, that is easily accomplished with a couple of methods (Me.TransparencyKey and Me.Opacity), unfortunately the dropshadow effect of an image loaded or drawn in the form won't be transparent since the Form doesn't support Transparency as a backcolor.
That is, you can't set the form's background color to Transparent, it doesn't support that.
You can set the TransparencyKey to the form's background, and that color won't be rendered, so the form "appears" to be transparent. You can have any controls or draw any images, or load an image into the BackgroundImage (assuming the "background" color of the image loaded matches the TransparencyKey) and the form will appear "shaped" or the controls will appear to be floating.
You can then change the Opacity property of the form to see through those controls or images.
But, if you loaded an image (or drew the image) on the form, that has diminished alpha values (like a gradient shadow), the alpha blend is with the Form's backcolor, not the color that you "see" through the transparent area (since the color is not really transparent, just not rendered).
So, the lower alpha color of the image is blended with whatever the background color of the form is, which now makes that pixel a "blended" color, no longer the TransparencyKey color, so shows up as a fully opaque blend of the two colors (assuming the form was fully opaque).
If the form wasn't fully opaque, then you're mixing a diminished alpha background color (which is still fully transparent because of the key color) with your diminished alpha value in your image, so the result is a semi-transparent blend of the two.

Bottom line, if you set the C# (using LayeredWindow API) to 50% opacity, and you set a .Net form to 50% opacity, the image with alpha gradient shadow would look similar in both, and if not directly compared could be considered to be the same effect, but if both are raised to 100% opaque, the .Net shadow would be a solid dark gradient of the forms background color (not looking so good), where as the layered window gradient would be blended with the desktop and look much better.

edit: I went ahead and put together a quick example of a "shaped" form in .Net.
The fact is, the form isn't technically shaped. You could shape the form using Me.Region, but that actually refreshes the screen slower than using TransparencyKey for essentially the same effect.
If you had the TransparencyKey set, and you modified what you drew on the form, you could be "morphing" the form into all sorts of shapes rather easily.
The drawback is, you can't enable doublebuffering, so the drawing can be a bit flashy for rapid redraws. If you enable double buffering, the form is rendered from the BufferedGraphics as a straight buffer to screen, so the TransparencyKey filter can't filter the keyed pixels during the rendering, so you see the rectangular background color of the form where you wanted transparency.

As a simple example, the attached project just sets the background of the form transparent using the TransparencyKey property, and draws an ellipse path with a PathGradientBrush giving a toroid shape look to the ellipse.
It uses a timer to move the form around the primary screen, so you have this "ring" moving around the screen.
If you can click (catch) and drag on ring with the left mouse button, you can reposition the window. It will start moving again once you release it.
If you click on it with the right mouse button, the application closes.
Attached Files
File Type: zip CatchMeDragMe.zip (16.5 KB, 9 views)
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 04-18-2012 at 02:31 PM. Reason: Added a simple example
Reply With Quote
  #17  
Old 04-21-2012, 03:25 AM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default DrawImageUnscaled method, C# calling InteropServices and alpha texture effect

To AtmaWeapon...thanks for the clarification of the DrawImageUnscaled method.
Yes, both the naming of the method, and what is implied by the MSDN docs,
are both confusing.

Quote:
Originally Posted by passel
It probably wouldn't be too hard to port, although it seems to be something you've been wanting to avoid.
I still remember the C# port over of the Perlin Noise that didn't go so well
(which you had to clean-up the VB.net code to get it working..)

The forms' Me.TransparencyKey, Me.Opacity, and Me.Region properties definitely offer a variety of options.

There interesting part of the "CatchMeDragMe.zip" attachment code is the shadowing behind the ring.
It varies depending on the computer you run it on
as well as how fast the ring is dragged.
Is there anyway to "stabilize" the drop shadow offset behind the ring
irregardless of changes in drag speed?

Your code reminds me a bit of this codeproject article.

I've been playing around with the texturebrush code I linked to in post #8 of this thread,
and managed to merge it to use the fastpix lockbits wrapper.
Please check out the attachment.
It creates (and shows) a greyscale-on-the-fly version of the texture image fairly quickly.

The next thing I need to work on is a demo that is essentially
the reverse of the code in the attachment.
The demo would have a greyscale image extracted from image-with-overlay graphic,
by comparing it to a image-without-overlay graphic and save the greyscale
graphic to a file.

Then, once the greyscale images are created, they can be used
to set the alpha for red, green, blue parts of the 32bpp format pixel arrays.

I would prefer than instead of a single alpha combined mask
that individual red green and blue channel mask be created.

Then shape-clipped alpha texturebrush fills can be overlaid
using multiple greyscale masks
to form sophisticated layer animation effects.

Haven't seem any lockbits demos that allow setting
tween points between morphing keyframes,
but I will keep on looking..
Reply With Quote
  #18  
Old 04-25-2012, 09:57 PM
passel's Avatar
passel passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 7,862
Default

Well, I'll be on my way to the Science Festival tomorrow, so before I hit the road, I thought I'd take a quick look at the last attachment.
I guess I've seen the code before, and I remember thinking that no one made a comment on the web page about the comments to a bit of code.
Code:
' The white-most pixels will have the the most transparency (highest alpha), 
' and the dark-most pixels will have the least transparency.
"(highest alpha)" would be the most opaque, not most transparent.
The code does indeed set the alpha based on the whiteness of the pixel, so the comment is backwards.
The White-most pixels will be the least transparent (the whiteness will show in the merged image), where the dark pixels will not obscure the image (most transparent).

Of course, you don't actually have to use the lockbits code and loop to change the alpha values.
Since you are using a color matrix to create the grayscale image, you could modify the alpha of the pixels at the same time with the one color matrix.

Modifying a couple of your routines:
First, we'll pass the transparency value to the MakeImageGrayscale routine, so it can do both operations simultaneously.
Then we can comment out the FastPix stuff.
The third modification is to add picTextured.Refresh() after you've updated the picTextured.Image in the AdjustPixels routine so that you see the texture update immediately as you move the slider, rather than having to wait for you to pause moving long enough for the paint event to occur.
The mouse move events I believe have a higher priority (at least when a button is down and dragging) than paint events, so the paint event will be held until the drag slows enough that other events can squeeze in.
The .Refresh method will force the paint event to occur "now" rather than when convienient.
Code:
'Added Refresh call at the end
  Private Sub AdjustPixels()
    lblValue.Text = tbarTransparency.Value
    Dim transparency As Single = tbarTransparency.Value / (tbarTransparency.Maximum - tbarTransparency.Minimum)
    Dim bmp As New Bitmap(picBmp.Image)       ' Take a copy
    Dim txtr As New Bitmap(picTxtr.Image)     ' Make sure the image is in the proper format
    AlphaTexturize.BitmapTexture.ApplyTexture(bmp, txtr, transparency)
    picTextured.Image = bmp
    picTextured.Refresh()
  End Sub

'MakeImageGrayscale:
'Modified to add "transp" (transparency) to the parameter list
'Modified the ColorMatrix to use that value.
'Since the ColorMatrix converts the image to Grayscale, all the color values (R,G,B) will be the same 
'so it is convenient to just chose one of them (red in this case) in the Alpha column (4th column) to scale the alpha value.
'The alpha row's (4th row) 4th column needs to be 0 (rather than 1) so that it doesn't
'effect the alpha value being determined by the red value.

'I changed the meaning of bm_source. 
'The original code used the color matrix to draw from the bitmap onto itself, so since the
'alpha was 255, the grayscaled version completely replace the original image.
'If we want to modify the alpha, we can't draw on top of the original image or we will simply
'get a alpha modified gray scale pixel blended with the original image.
'So, bm_source is now set to a copy of the the original bitmap, the original bitmap is cleared
'to be fully transparent (all 0's, like a new bitmap created without an image), so that our
'color matrix can render the bm_source and "merge" it with the zero'd bitmap, so the result
'is exactly what the color matrix produces, which is our desired alpha modified grayscaled image.

    Private Shared Sub MakeImageGrayscale(ByVal bmp As Bitmap, ByVal transp As Single)
      Dim cMatrix As New ColorMatrix(New Single()() _
       {New Single() {0.299, 0.299, 0.299, transp, 0}, _
       New Single() {0.587, 0.587, 0.587, 0, 0}, _
        New Single() {0.114, 0.114, 0.114, 0, 0}, _
        New Single() {0, 0, 0, 0, 0}, _
        New Single() {0, 0, 0, 0, 1}})
      Dim scale_factor As Single = 0.4
      Dim imageAttrib As New ImageAttributes
      imageAttrib.SetColorMatrix(cMatrix)
      Dim gr As Graphics = Graphics.FromImage(bmp)
      ' Apply the grayscale image attribute
      ' Get the source bitmap.
      Dim bm_source As New Bitmap(bmp)
      gr.Clear(Color.Transparent)
      gr.DrawImage(bm_source, New Rectangle(0, 0, bmp.Width, bmp.Height), _
       0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, imageAttrib)
      ' Make a bitmap for the result.
      Dim bm_dest As New Bitmap( _
          CInt(bm_source.Width * scale_factor), _
          CInt(bm_source.Height * scale_factor))
      ' Make a Graphics object for the result Bitmap.
      Dim gr_dest As Graphics = Graphics.FromImage(bm_dest)
      ' Copy the source image into the destination bitmap.
      gr_dest.DrawImage(bmp, 0, 0, _
          bm_dest.Width + 1, _
          bm_dest.Height + 1)
      ' Display the result.
      If Form1.picDest.Image IsNot Nothing Then
        Form1.picDest.Image.Dispose()
      End If
      Form1.picDest.Image = bm_dest
      'Clean-up
      gr.Dispose()
      gr_dest.Dispose()
      'bm_dest.Dispose()
      bm_source.Dispose()
    End Sub

'Now that the alpha has already been modified at the time we converted the image to grayscale, we no longer need the FastPix looping code

    Public Shared Sub ApplyTexture(ByVal bmp As Bitmap, _
      ByVal texture As Bitmap, _
      ByVal textureTransparency As Single)
      'Basic error checking..
      If (bmp Is Nothing) OrElse (texture Is Nothing) Then Throw New ArgumentNullException
      If textureTransparency < 0 OrElse textureTransparency > 1 Then
        Throw New ArgumentOutOfRangeException("textureTransparency must be between 0 and 1.")
      End If
      ' Convert the texture to grayscale before using it
      MakeImageGrayscale(texture, textureTransparency)
      'Dim x, y, alpha As Integer
      'Using fp As New FastPix(texture)
      ' Adjust the alpha value of each pixel in the texture bitmap.
      ' The white-most pixels will have the the most transparency (highest alpha), 
      ' and the dark-most pixels will have the least transparency.
      'For x = 0 To texture.Width - 1
      '  For y = 0 To texture.Height - 1
      '    Dim c As Color = fp.GetPixel(x, y)
      '    ' c.R -> all of the RGB values are the same since the image is in grayscale
      '    alpha = CInt(c.R * textureTransparency)
      '    c = Color.FromArgb(alpha, c)
      '    fp.SetPixel(x, y, c)
      '  Next
      'Next
      'End Using
      Dim gr As Graphics = Graphics.FromImage(bmp)
      Dim myBrush As New TextureBrush(texture)
      ' Draw the texture over the original bitmap
      gr.FillRectangle(myBrush, bmp.GetBounds(GraphicsUnit.Pixel))
      myBrush.Dispose()
      gr.Dispose()
    End Sub
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 04-25-2012 at 10:08 PM.
Reply With Quote
  #19  
Old 04-26-2012, 03:35 PM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default Towards one pass pixel altering..

Quote:
Well, I'll be on my way to the Science Festival tomorrow, so before I hit the road..
Thanks for taking the time to post before you hit the road.
Quote:
The third modification is to add picTextured.Refresh() after you've updated the picTextured.Image in the AdjustPixels routine so that you see the texture update immediately as you move the slider, rather than having to wait for you to pause moving long enough for the paint event to occur.
The mouse move events I believe have a higher priority (at least when a button is down and dragging) than paint events, so the paint event will be held until the drag slows enough that other events can squeeze in.
The .Refresh method will force the paint event to occur "now" rather than when convenient.
I was not aware of this prioritization.
Is there any MSDN documentation that shows (like in a chart or diagram) the prioritization of events under .Net?
I'm still trying to get used to the way delegates interplay with events.

I found this that said:
Quote:
An event is just a formalized software pattern in which a notification source makes callbacks to one or more handler methods. Events are therefore similar to interfaces and delegates because they provide a means to design applications that use callback methods. However, events add a valuable degree of productivity because they are easier to use than interfaces or delegates.
Every event is defined in terms of a particular delegate type. For each event defined by an event source, there is a private field that is based on the event's underlying delegate type. This field is used to track a multicast delegate object. An event source also provides a public registration method that allows you to register as many event handlers as you'd like.
When you create an event handler (a delegate object) and register it with an event source, the event source simply appends the new event handler to the end of the list. An event source can then use the private field to call Invoke on the multicast delegate which, in turn, will execute all the registered event handlers.
Invoking on the multi-cast delegates..this totally lost me.

This is what the MSDN has to say about events:
Quote:
An event is a message sent by an object to signal the occurrence of an action. The action could be caused by user interaction, such as a mouse click, or it could be triggered by some other program logic. The object that raises the event is called the event sender. The object that captures the event and responds to it is called the event receiver.
In event communication, the event sender class does not know which object or method will receive (handle) the events it raises. What is needed is an intermediary (or pointer-like mechanism) between the source and the receiver. The .NET Framework defines a special type (Delegate) that provides the functionality of a function pointer.
A delegate is a class that can hold a reference to a method. Unlike other classes, a delegate class has a signature, and it can hold references only to methods that match its signature. A delegate is thus equivalent to a type-safe function pointer or a callback.
Type safe function pointer?
Class that can hold a reference to a method?
Things were so much easier under VB6.

I agree that to "do both operations simultaneously"
(everything in one pass) is more efficient so I'll try to integrate
your code into the AdjustPixels attachment..
Reply With Quote
  #20  
Old 05-03-2012, 07:57 PM
surfR2911 surfR2911 is offline
Contributor
 
Join Date: Oct 2009
Posts: 719
Default Ever onward..

Hopefully passel has a good time at the Science Festival..

Well it took a while, but while passel was away,
I finally managed to scrap together a little time to merge passel's single pass color matrix adjusting
into the ongoing "AlterPixels" (and AlphaTexturize) code.

Thus, with new functionality, the "MakeImageGrayscale" sub becomes "AlphaModifiedGrayscale_PixelBlend" sub.
Quote:
Then we can comment out the FastPix stuff.
Whoa, not so fast..I intend to keep the FastPix code in and try to reuse it for other purposes.

With the performance increase of transforming a lockbits pixel changing loop to a single-pass color matrix adjust
the next logical step is to see if we could add some animation to alter the alpha texture at runtime.

If you run the "Adjust_pixels_rev1-dot_2.zip" code (attached below),
you should press the "Start Timer" to initial the swirl pixels animation,
which, if you use the trackbar slider control to adjust the transparency,
will show the effects of the animation on the alpha texture overlay.

Right now it gives fairly good performance even using SetPixel,
but there are two changes that would be desirable:
1.) To have the alpha texture continually updated in sync with the swirl
swirl animation (instead of just when the trackbar control is adjusted)
2.) To use the FastPix version of SetPixel (which uses LockBits),
instead of the Drawing2D version, which is somewhat slower.
I tried to integrate these changes but all my commented out changes are throwing
unhandled exception errors.

Perhaps readers of this thread maybe wondering (with all these "diversionary" posts):
"When are we getting back to fuzzy lines?"
Have no fear..even though it seems like we are taking "the long way 'round",
we'll get there eventually after a little more alpha masking
(and maybe some rgb channels) exploration.

Anyway..it took quite a while to find a "clean" version of the blue variegated NBR (PBS Nightly Business Report) background,
but after searching through hours and hours of videos frame by frame
I finally found a single frame with the right (clean) background graphic.

I took this into Photoshop and created multiple splatter brush lines with Gaussian blurred pixels.
Then I combined the clean background side-by-side with the fuzzy splattered lines version
so hopefully some code came be found to generate a combined-RGB Alpha Composite mask
from analyzing the pixel differences between the two graphics.
I'll try to include the unflattened psd (photoshop) files,
(if I can get the zip attachment size under the forum limit).

An intermediate step to do this is to have multiple color matrix effects occurring in a single pass.

The AlterPixels1.2 attachment below does that but it needs to have the color matrix blurring
code from the "A visit to the color matrix" post attachment (from the Perlin Noise thread) added in.

What I'm hoping is that variables (like X1 thru X17..or an array of variables) could be
substituted for the numerical values in Color Matrix creation code like:
Code:
      Dim cMatrix As New ColorMatrix(New Single()() _
       {New Single() {0.299, 0.299, 0.299, transp, 0}, _
       New Single() {0.587, 0.587, 0.587, 0, 0}, _
        New Single() {0.114, 0.114, 0.114, 0, 0}, _
        New Single() {0, 0, 0, 0, 0}, _
        New Single() {0, 0, 0, 0, 1}})
so that a code sequence of
different "If..Then" structures could test for different booleans like
blnAddAlphaAdjust, blnAddSinusoidalConvolution, blnAddGaussianBlur, etc,
and perform the relevant cumulative additive adjusts on the X1 thru X17 variable number values that are used (in turn) to generate the color matrix.

However I haven't found any examples of applying multiple pixel effects using single pass additive color matrix adjusting.
Please feel free to post any code/examples/links of this you may know of..
(that demonstrate how to do this). Thanks.

Last edited by surfR2911; 05-03-2012 at 08:17 PM.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->