ImageEn for Delphi and C++ Builder ImageEn for Delphi and C++ Builder

 

ImageEn Forum
Profile    Join    Active Topics    Forum FAQ    Search this forumSearch
Forum membership is Free!  Click Join to sign-up
Username:
Password:
Save Password
Forgot your Password?

 All Forums
 ImageEn Library for Delphi, C++ and .Net
 ImageEn and IEvolution Support Forum
 Evolution2
 New Topic  Reply to Topic
Author Previous Topic Topic Next Topic  

jez

20 Posts

Posted - Jul 01 2011 :  02:32:55  Show Profile  Reply
Hello,

I have been using the dot.net version for a while and have been experiencing some problems which hopefully you can help resolve. Specifically I have been running some simple image processing in a background worker thread by creating an IEImage control.

I have a sample VS2010 project that demonstrates the problem but I cant attach a zip or rar file to this message!!

The main form has an anchored IEViewer control on it but it does absolutely nothing. When the background thread runs and you resize the form, you get an AccessViolationException.

By accident, I noticed that if I call IEImage.ExecuteOpenDialog one time this really helps make the problem go away !

Would be good to understand what causes the crash and why the dialog box seems to make things much better.

Jez



fab

1310 Posts

Posted - Jul 01 2011 :  15:19:42  Show Profile  Reply
Hello,
have you a link where I can download the test project?
Go to Top of Page

jez

20 Posts

Posted - Jul 08 2011 :  05:41:08  Show Profile  Reply
fabrizio,
ive added the code from form1.vb and form1.designer.vb below. that should be enough to reproduce the problem. i see this type of error all the time in my proper application. you dont need the image file to reproduce this.
jez

>>>> form1.vb

Imports System.ComponentModel
Imports HiComponents.IEvolution
Imports HiComponents.IEvolution.IEImage

' use the ExecuteOpenDialog makes it much more robust (but I dont want to)
#Const USE_DIALOG = 0

Public Class Form1

Private WithEvents bgw As New BackgroundWorker
Private bgwImage As New HiComponents.IEvolution.IEImage
Private bCancel As Boolean

Public Sub New()

' This call is required by the designer.
InitializeComponent()

' Add any initialization after the InitializeComponent() call.
bgw.WorkerReportsProgress = False
bgw.WorkerSupportsCancellation = False
'
IeViewer1.Image.Width = 2452
IeViewer1.Image.Height = 2056
IeViewer1.Image.Format = PixelFormat.ie24RGB
'
bgwImage.Width = 2452
bgwImage.Height = 2056
bgwImage.Format = PixelFormat.ie24RGB

End Sub

Private Sub bgw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork

#If USE_DIALOG = 1 Then
Dim fname As String = bgwImage.ExecuteOpenDialog() ' you can click cancel or Ok it makes no difference
#Else
Dim fname As String = "Oscillation1.BMP"
#End If

Do While bCancel = False
bgwImage.LoadImage(fname)
bgwImage.Negative()
bgwImage.AdjustBrightnessContrastSaturation(90, 10, 0)
bgwImage.GammaCorrect(1.0)
Loop
End Sub

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
If Button1.Text = "Start" Then
bCancel = False
bgw.RunWorkerAsync()
Button1.Text = "Stop"
Else
bCancel = True
Button1.Text = "Start"
End If
End Sub

Protected Overrides Sub Finalize()
MyBase.Finalize()
bCancel = True
End Sub

End Class

>>>> end form1.vb

>>>> form1.designer.vb

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form

'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub

'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button()
Me.IeViewer1 = New HiComponents.IEvolution.IEViewer()
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.Button1.Location = New System.Drawing.Point(719, 23)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(52, 26)
Me.Button1.TabIndex = 1
Me.Button1.Text = "Start"
Me.Button1.UseVisualStyleBackColor = True
'
'IeViewer1
'
Me.IeViewer1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
Or System.Windows.Forms.AnchorStyles.Left) _
Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.IeViewer1.AutoCursors = True
Me.IeViewer1.CenterNewObjects = False
Me.IeViewer1.DelayDisplaySelection = True
Me.IeViewer1.DelayZoomFilter = False
Me.IeViewer1.DisplayGrid = False
Me.IeViewer1.EnableAnnotationsZoom = True
Me.IeViewer1.EnableInteractionHints = True
Me.IeViewer1.ForceALTkey = False
Me.IeViewer1.LayersDrawBox = False
Me.IeViewer1.LayersResizeAspectRatio = HiComponents.IEvolution.IEViewer.LayersResizeAspectRatioType.ALTKey
Me.IeViewer1.LayersRotateStep = 45
Me.IeViewer1.LayersRotationAntialias = False
Me.IeViewer1.LayersSelectConstrains = True
Me.IeViewer1.Location = New System.Drawing.Point(0, 0)
Me.IeViewer1.Name = "IeViewer1"
Me.IeViewer1.ObjectMaxMovingDistance = 1
Me.IeViewer1.ObjectsEnableFastDrawing = True
Me.IeViewer1.ObjectsSelectOnMouseDown = True
Me.IeViewer1.ObjectsUseCentralGrip = False
Me.IeViewer1.ObjGripShape = HiComponents.IEvolution.IEGripShape.Circle
Me.IeViewer1.RightToLeft = System.Windows.Forms.RightToLeft.No
Me.IeViewer1.SelectionAspectRatio = -1.0R
Me.IeViewer1.SelectionGridSize = 1
Me.IeViewer1.Size = New System.Drawing.Size(705, 411)
Me.IeViewer1.SmoothScrollValue = 8
Me.IeViewer1.TabIndex = 0
Me.IeViewer1.TransitionTiming = HiComponents.IEvolution.IEViewer.IETransitionTiming.Linear
Me.IeViewer1.VideoCaptureFitFreeze = True
Me.IeViewer1.VideoCaptureShowVideo = False
Me.IeViewer1.VideoCaptureSource = 0
Me.IeViewer1.ViewX = 0
Me.IeViewer1.ViewY = 0
Me.IeViewer1.Zoom = 100.0R
Me.IeViewer1.ZoomSelectionAspectRatio = True
Me.IeViewer1.ZoomX = 100.0R
Me.IeViewer1.ZoomY = 100.0R
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(781, 411)
Me.Controls.Add(Me.Button1)
Me.Controls.Add(Me.IeViewer1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)

End Sub
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents IeViewer1 As HiComponents.IEvolution.IEViewer

End Class
>>>> end form1.designer.vb
Go to Top of Page

fab

1310 Posts

Posted - Jul 09 2011 :  10:36:41  Show Profile  Reply
Unfortunately I have not been able to assemble a working solution. Please in order to speedup my help, could you let me download a working Visual Studio solution?
Go to Top of Page

jez

20 Posts

Posted - Jul 11 2011 :  01:40:06  Show Profile  Reply
try this:

http://hidemyass.com/files/BwdJq/
Go to Top of Page

fab

1310 Posts

Posted - Jul 14 2011 :  14:02:54  Show Profile  Reply
You use the same object (bgwImage) in multiple threads. I think (actually I suppose) that you should create an IEImage object for each thread, instead of using the instance bgwImage field. For example:


Private Sub bgw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
        Dim fname As String = "Oscillation1.BMP"
        Do While bCancel = False
            Dim bgwImage As New HiComponents.IEvolution.IEImage      <<<<
            bgwImage.LoadImage(fname)
            bgwImage.Negative()
            bgwImage.AdjustBrightnessContrastSaturation(90, 10, 0)
            bgwImage.GammaCorrect(1.0)
            bgwImage.dispose()               <<<<<<<
        Loop
    End Sub


Of course you have to remove the instance field bgwImage.

Please accept my apologies for possible errors, I don't know VB.Net.


Go to Top of Page

jez

20 Posts

Posted - Jul 18 2011 :  01:44:21  Show Profile  Reply
Thanks for the input but I dont really see what's up with my version. I create an IEImage object, initialise it in the constructor and then use it exclusively in the background thread. This still breaks when the unconnected IEViewer object on the form is resized. Are these objects simply not thread-safe !!

I changed your code sample to the following:-

Private Sub bgw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
Dim fname As String = "Oscillation1.BMP"
Dim bgwImage As New HiComponents.IEvolution.IEImage
bgwImage.Width = 2452
bgwImage.Height = 2056
bgwImage.Format = PixelFormat.ie24RGB
Do While bCancel = False
bgwImage.LoadImage(fname)
bgwImage.Negative()
bgwImage.AdjustBrightnessContrastSaturation(90, 10, 0)
bgwImage.GammaCorrect(1.0)
Loop
bgwImage.Dispose()
End Sub

This still crashes in exactly the same way as my first example. Start the thread, resize the form and KABOOM - Invalid access.

Are you able to explain what causes the crash and why the use of ExecuteOpenDialog on the background IEImage appears to fix the problem!

Jez

Go to Top of Page

fab

1310 Posts

Posted - Jul 18 2011 :  02:33:54  Show Profile  Reply
There is no exception here with your project, I'm sorry (tested with Visual Studio 2010, Win 7 - 32bit).
IEvolution objects can be used inside threads. Multiple threads cannot access the same object, unless you implement locking mechanisms yourself.
Go to Top of Page

jez

20 Posts

Posted - Jul 18 2011 :  04:58:55  Show Profile  Reply
Are you clicking the Start button to get the background thread running ?
Go to Top of Page

fab

1310 Posts

Posted - Jul 18 2011 :  06:47:08  Show Profile  Reply
Yes!
Go to Top of Page

jez

20 Posts

Posted - Jul 18 2011 :  07:23:22  Show Profile  Reply
And then you grab the forms resize handles and resize the form ?

and it doesn't crash !! For me it does almost every time.

I don't get it! What version of Evolution2 are u using. I have 3.1.2.0

I've tried to attach a jpeg screenshot to this message but I get:-

Microsoft VBScript runtime error '800a004c'

Path not found

/imageen/forum/outputFile.asp, line 159

Go to Top of Page

fab

1310 Posts

Posted - Jul 18 2011 :  07:51:42  Show Profile  Reply
I am using last version released, 3.1.2.
Please could you locate the instruction where the exception occurs (LoadImage, Negative, AdjustBrightnessContrastSaturation, ....), excluding each one if necessary?

Also, in order to try to replicate this problem, I'd like to test the same image you are loading. Could you send it?

I just noticed xequte about the images upload problem.
Go to Top of Page

jez

20 Posts

Posted - Jul 19 2011 :  06:11:04  Show Profile  Reply
You don't need to load an image. The following code crashes:-

Private Sub bgw_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
Dim bgwImage As New HiComponents.IEvolution.IEImage
bgwImage.Width = 2452
bgwImage.Height = 2056
bgwImage.Format = PixelFormat.ie24RGB
Do While bCancel = False
bgwImage.Negative() '<--- this crashes when the form is resized
Loop
bgwImage.Dispose()
End Sub

Any calls made on an IEImage object are likely to crash for the same reason.

I have two IEImage objects in two different threads, do I need to apply some synlocking/mutex ? Since they are different objects I didnt expect to have to do that.

J
Go to Top of Page

fab

1310 Posts

Posted - Jul 20 2011 :  01:45:59  Show Profile  Reply
Ok, now I can replicate the crash, but only on resizing.
Please wait while we try to identify the problem.
Go to Top of Page

fab

1310 Posts

Posted - Jul 20 2011 :  03:41:43  Show Profile  Reply
Problem (bug) found. Next release will include the fix.

Thank you.
Go to Top of Page

jez

20 Posts

Posted - Jul 20 2011 :  04:11:32  Show Profile  Reply
That's good to hear.

I see this problem in my application a lot (the code you have is a test case), not just when resizing, also when dragging a selected rectangle around can often do the same.

I have two separate IEImage objects in two different threads, do I need to apply some synlocking/mutex ? Since they are different objects I didnt expect to have to do that.

It was also very strange that a call to ExecuteOpenDialog seems to make the problem go away. Can you explain the bug a little more ?

J
Go to Top of Page

fab

1310 Posts

Posted - Jul 20 2011 :  04:17:51  Show Profile  Reply
It is a Delphi library related question. ExecuteOpenDialog contains IEMulti, which in turn starts some threads inside. Starting a thread in Delphi enables the whole application to mutithreading (instead of ExecuteOpenDialog you could also create/destroy a IEMulti object).
Go to Top of Page

jez

20 Posts

Posted - Jul 20 2011 :  06:58:14  Show Profile  Reply
That is a really nice workaround. Thanks.
Go to Top of Page
  Previous Topic Topic Next Topic  
 New Topic  Reply to Topic
Jump To: