|
Hello gurus,
I'd really need someone advanced in graphics since I have a weird error which I can't locate at all. I think it's connected with a piece of code that's supposed to display a grayscale image:
arrayImage = dpx.GS16ArrayFromRawArray(dpx.DPXPixelArray)
gch = GCHandle.Alloc(arrayImage, GCHandleType.Pinned)
Dim pBuf As IntPtr = gch.AddrOfPinnedObject
Dim stride As Integer = Width * 2
Me.CurrentBitmap = New Bitmap(Width, Height, stride, Imaging.PixelFormat.Format16bppGrayScale, pBuf)
gch.Free()
I might have to mention that I use the exact same process (with adapted parameters) to read an RGB image from a byte array (24bppRGB). The image data in this case are supplied as an array of UInt16 - and the values seem to fit. When stepping through the code, everything seems to be fine.... but a little bit later in connection with the update of a progressBar , I get an InvalidArgumentException.
The stack trace leaves me the following:
bei System.Drawing.Graphics.CheckErrorStatus(Int32 status)
bei System.Drawing.Graphics.DrawImage(Image image, Int32 x, Int32 y, Int32 width, Int32 height)
bei System.Drawing.Graphics.DrawImage(Image image, Rectangle rect)
bei System.Windows.Forms.PictureBox.OnPaint(PaintEventArgs pe)
bei System.Windows.Forms.Control.PaintWithErrorHandling(PaintEventArgs e, Int16 layer, Boolean disposeEventArgs)
bei System.Windows.Forms.Control.WmPaint(Message& m)
bei System.Windows.Forms.Control.WndProc(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
bei System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
bei System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
bei System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
bei System.Windows.Forms.Application.Run(ApplicationContext context)
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
bei Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
bei HeadersTwo.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:Zeile 81.
bei System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
bei System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
bei Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
bei System.Threading.ThreadHelper.ThreadStart_Context(Object state)
bei System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
bei System.Threading.ThreadHelper.ThreadStart()
Does anyone of you probably have an idea where to start looking for the error?
Thanks a lot!
Mick
|
|
|
|
|
I am pretty sure your calculation of stride is wrong, unless it means something different to what it meant when I used the term in my image processing days. I am also surprised that a 16 bit conversion exists inside the framework, but I guess it looks like it does.
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
Hi,
yes you can construct an image/bitmap from raw data with one of its constructors.
However the documentation clearly states "The caller is responsible for allocating and freeing the block of memory specified by the scan0 parameter, however, the memory should not be released until the related Bitmap is released." so the way I understand it is you should not free the GCHandle right away, the raw data should not be allowed to move around for as long as your bitmap is alive.
|
|
|
|
|
Aahhh - I see! I thought I had taken care of this issue by assigning the new bitmap to the Me.CurrentBitmap property, which is later used as the source of a picture box... I should have assigned a copy and then freed the original, right?
What do you say regarding Christian's hint about the stride parameter?
[EDIT:]
I just replaced the relevant lines with
Dim arrBmp As New Bitmap(Width, Height, stride, Imaging.PixelFormat.Format16bppGrayScale, pBuf)
Me.CurrentBitmap = New Bitmap(arrBmp, arrBmp.size)
gch.Free()
and now I'm receiving an ArgumentException in the second line.
modified on Wednesday, September 2, 2009 2:20 PM
|
|
|
|
|
Hi,
1. yes, a good approach would be to create the bitmap, make a copy, dispose of the original, then free the GCHandle. The bad thing is this temporarily takes twice the amount of memory.
2. MSDN says stride must be a multiple of 4, so width should be even (or rounded up, raw data permitting).
3. you have to look at Exception.ToString() to get all the available details. If still insufficient, experiment with different parameter combinations. And maybe after all, 16-bit isn't supported after all? the doc says it gets converted to some other format right away.
|
|
|
|
|
Hi Luc,
I'll follow that approach. Btw it's been your own idea from an older thread.
Width is 1024, so I guess it should be allright.
Exception.ToString() shows a ArgumentException "Invalid Parameter". Finally it refers to the line where I try to assign the first bitmap to a new one... Does that tell you anything? Since that happens when I try to assign the 16-bit-Grayscale format to a regular bitmap, I'm afraid it really might not be supported. Or - as the doc says - that it's converted to anything special that doesn't want to be converted to a normal thing...
Since I actually just want to display a grayscale, I could anyway live much better with 8-bit. BUT: There's no such PixelFormat as "8bppGrayscale", just indexed colours which loads (!) but shows a weird picture of course. Do you by any chance know which PixelFormat I'd have to choose for a simple grayscale image?
Thanks
Mick
|
|
|
|
|
Michael Schäuble wrote: your own idea Wink from an older thread.
yep. copying an image solves a file-locked problem in Image.FromFile; using FromStream does the same.
I have used this code:
byte[] bytes=new byte[32*1024];
GCHandle handle=GCHandle.Alloc(bytes, GCHandleType.Pinned);
IntPtr ptr=handle.AddrOfPinnedObject();
Bitmap bm1=new Bitmap(16, 16, 1024, PixelFormat.Format8bppIndexed, ptr);
log("bm1 OK");
Bitmap bm4=new Bitmap(1000, 1000);
Graphics g=Graphics.FromImage(bm4);
g.DrawImage(bm1, 0, 0);
log("bm4 drawn");
Bitmap bm2=new Bitmap(bm1);
bm1.Dispose();
handle.Free();
Bitmap bm3=new Bitmap(bm2);
bm2.Dispose();
log("size ="+bm3.Size);
bm3.Dispose();
to experiment and find out which formats are acceptable; it seems Format16bppGrayScale is the
odd one out: .NET is willing to construct a bitmap (bm1) but refuses to use it (either in bm4 or in bm2)
Work arounds:
1.
Format1bppIndexed is the one closest to what you could use, but I have no idea on how to install an appropriate lookup table.
2.
What is bound to work is convert the raw data to a format that will be understood, such as Format32bppRgb
All it takes is replacing each 16-bit value X by a new value Y where Y equals something like X/4 * 0x1010101 which assumes X has 10 significant bits, so 2 bits need to be thrown out, and the gray value gets copied to all bytes (that's what the multiplication does when using unsigned arithmetic).
modified on Wednesday, September 2, 2009 3:59 PM
|
|
|
|
|
Hello everyone,
I got a really strange problem. I could make 2 computers to communicate to each other through hyperterminal, 115200,8,n,1 Hardware(CTS,RTS).
Then I decide to make a VB6 program in one of those (with the same parameters). Sending data from VB6 is just fine (the hyperterminal in the other computer shows the same data), but when it receives any data the program crashes and the program manager shows 99% of the cpu is beings used by VB6
Note.: There´re no infinite loops neither "OnComm" function is avaible in the algorithm.
Did anyone have this problem? Or knows how to solve it?
Thanks
|
|
|
|
|
Why would you use VB6 ? It's out of date, and was always rubbish.
Christian Graus
Driven to the arms of OSX by Vista.
Read my blog to find out how I've worked around bugs in Microsoft tools and frameworks.
|
|
|
|
|
Well, it´s easy to program and does not need the whole .net framework to run with.
I know it´s out of date, but it´s still reliable for simple tasks and even really old pcs can run.
Thanks but...
Does anyone have a clue about it?
|
|
|
|
|
STOP throw out what you have started, download VB.net express and start again. You are using a tool that is no longer supported.
|
|
|
|
|
No matter how obsolete and outdated your chosen language is, Windows always has and always will require you to not touch controls from any thread other than the one that created the control, and my best guess is you are trying to receive and somehow display incoming serial data on a different thread (most asynchronous operations run on some other thread automatically).
This little article[^] describes the problem and solution in .NET (using C# examples); I don't know how it looks in ancient VB.
|
|
|
|
|
My trig skills are lacking, please assist if possible.
Given the coordinates of three points of an arc, how do I calculate the origin and radius of the arc or circle.
Dim s As String() = Split("a 100 100 76 110 50 100", " ")
Dim x1 As Integer = CInt(s(1))
Dim y1 As Integer = CInt(s(2))
Dim x2 As Integer = CInt(s(3))
Dim y2 As Integer = CInt(s(4))
Dim x3 As Integer = CInt(s(5))
Dim y3 As Integer = CInt(s(6))
e.Graphics.DrawArc(Pens.Green, x, y, width, height, angle1, angle2)
|
|
|
|
|
Hi, this is not a programming question, it is a math question, and as such language independent.
Here is one way to solve it:
- choose two of the three points, and find the line that holds all points at an equal distance of them (that line is perpendicular on the line that connects them).
- choose another set of two of those three points, and find again the line that...
- the center of the circle is bound to be at the intersection of those two lines.
So that is your solution, you can work about the formulae and the code yourself.
|
|
|
|
|
Yes, it is a math question... which is why I stated that my trigonometry skills are lacking. If I knew the formulas to do as you suggested, I wouldn't be asking the question to begin with. I do; however, appreciate the feedback.
I am researching the math, but don't have a lot of time to come up with the solution. If anyone can help by showing me the correct formula to use I would very much appreciate the assistance.
|
|
|
|
|
oh nice. so you are one-voting me and asking to be spoon fed at the same time?
I have news for you: this is not a hand-me-the-code kind of site, this is a site for serious people making and showing an effort and asking for help when they get stuck in the middle of it; or alternatively asking for general advice (which I gave you) before starting something.
And to all people that don't have the time, my advice is to either work harder or start earlier, or both. I'm not impressed.
|
|
|
|
|
I'm not asking to be spoon fed the code. Just asking if anyone knows the formula.
Yes, I'm also searching with google and I'm already working through some trig tutorials to figure out the math. Now, if you will stop wasting time by posting non-answers, I'll get back to my research.
|
|
|
|
|
Hello everybody,
in my project I have a pictureBox, sitting in one of the panels of a SplitContainer and docking to it in fill mode. The PictureBox loads it's images in zoom mode and is supposed to take the size of the loaded/zoomed image automatically whenever a) the form's size is changed or b) the splitter is moved.
In a first approach to reach this I call
Private Sub FitPictureBox()
If PictureBox1.Image IsNot Nothing Then
Dim thisFrame As Bitmap = PictureBox1.Image
AspectRatio = thisFrame.Width / thisFrame.Height
SplitContainer3.SplitterDistance = PictureBox1.Width / AspectRatio
End If
from the 'resize' event as well as from the 'splitter.moved' event.
Now I'm desperately struggling to make this work, coz the 'resize' event (as well as the layout event) calling 'FitPictureBox' triggers the 'splitter.moved' event again - and I run into a loop i.e. a 'stack overflow' exception. Still I need to consider fitting the PictureBox in both cases.
Could anyone of you please guide me a way out of this dilemma? Did I use the wrong events or is there a better approach at all?
Thank you,
Mick
|
|
|
|
|
Hi, I have also had similar problems in the past with events causing other events to fire. I have found a way around this but really don't think it is the best way, so it will be interesting for me also to see other people's responses.
What I have done in the past is set a global variable and check that variable in the event handlers. So, at the start of your 'resize' event set a variable, say 'Resizing' to True, then in your splitter.moved event, check the state of 'Resizing', if False then do the event. Just remember to set 'Resizing' back to nothing at the end of the 'Resize' event.
Like I said, I don't think this is the best solution, seems a little dirty to me but it works.
|
|
|
|
|
Liqz wrote: so it will be interesting for me also to see other people's responses
Nope - this is exactly the method I use, form level booleans called bLoading sprinkled throughout the app.
|
|
|
|
|
Ah OK fine. I just thought that I might have been missing something native to the .Net framework which does a similar job. But thanks for the reassurance, I shall be more confident in my approach in the future
|
|
|
|
|
If I understand you correctly, the picuterbox is supposed to fit itself to the size of the SplitContainer after the container's size is changed (in whatever way).
Can you do something like this?
1. the container size changes
2. measure the size of the container
3. measure the size of the picturebox
4. if the picturebox's size is (already) correct, do nothing; if it is incorrect call your sub (and do whatever else).
Or what Liqz said...
My advice is free, and you may get what you paid for.
|
|
|
|
|
Wow - I didn't expect such quick responses Thank you both for the ideas!
@Liqz: that's exactly what I tried since I posted. Somehow it seems that the events are fired not only once - so when resetting the flag variable (just by chance I had also called it 'resizing') back to FALSE at the end of the 'resize' event, the problem arises again when it fires a second time...
@Johan:
I don't exactly know the sequence of the different events - resizing of the form might trigger the resize event for a main SplitContainer I have in it AND the resize event of a second SplitContainer which then holds the PictureBox. Do you probably know a way how to find out which event exactly fired my sub?
|
|
|
|
|
Liqz's approach finally worked out well for me after changing the last line in my sub to SplitContainer3.SplitterDistance = SplitContainer3.Width / AspectRatio
It seems as if the dependency between the SplitterDistance and the size of the PictureBox set some built-in event-devils free
Thank you both
|
|
|
|
|
You're welcome, glad I could be of assistance
|
|
|
|
|