Welcome Guest! To enable all features, please Login or Register.

Notification

Icon
Error

Options
View
Last Go to last post Unread Go to first unread post
#1 Posted : Monday, October 1, 2007 5:42:04 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


I'm trying to save a RasterImage to a SQL database via a MemoryStream with little success.  It appears that my examples in the documentation all save to a file, but if I'm overlooking something sorry for wasting your time.  Anyway, the first save works fine under most circumstances, but after saving another image I get the following exception message:

"Attempted to read or write protected memory.  This is often an indication that other memory is corrupt."

If I try to save again after the exception (which I catch), I get the following exception message:

"Invalid parameter passed."

I'm developing in C# with .NET 2.0 and LeadTools v. 15.  Below is the code where I load my SqlParameter object.  I start the RasterCodec engine at the beginning of a try and shut it down in the matching finally.  What am I doing wrong?

                            if (image.HighResolutionImage != null)
                            {
                                codecs = new RasterCodecs();
                                MemoryStream memoryStream = new MemoryStream();

                                codecs.Save(
                                    image.HighResolutionImage, memoryStream, RasterImageFormat.Cmp, 24);
                                byte[] blob = memoryStream.GetBuffer();
                                SqlParameter parameter = new SqlParameter(
                                    "@picture",
                                    SqlDbType.Image,
                                    blob.Length,
                                    ParameterDirection.Input,
                                    false, 0, 0, null,
                                    DataRowVersion.Current,
                                    blob);
                                sqlCmd.Parameters.Add(parameter);
                                memoryStream.Close();
                                codecs.Dispose();
                            }

                            if (image.LowResolutionImage != null)
                            {
                                codecs = new RasterCodecs();
                                MemoryStream memoryStream = new MemoryStream();

                                codecs.Save(
                                    image.LowResolutionImage, memoryStream, RasterImageFormat.Cmp, 24, 1, 1, 1, CodecsSavePageMode.Replace);
                                byte[] blob = memoryStream.GetBuffer();
                                SqlParameter parameter = new SqlParameter(
                                    "@thumbnail",
                                    SqlDbType.Image,
                                    blob.Length,
                                    ParameterDirection.Input,
                                    false, 0, 0, null,
                                    DataRowVersion.Current,
                                    blob);
                                sqlCmd.Parameters.Add(parameter);
                                memoryStream.Close();
                                codecs.Dispose();
                            }




 

Try the latest version of LEADTOOLS for free for 60 days by downloading the evaluation: https://www.leadtools.com/downloads

Wanna join the discussion? Login to your LEADTOOLS Support accountor Register a new forum account.

#2 Posted : Monday, October 1, 2007 11:33:48 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

Which line from above throws that error?  What's the stack-trace of that exception?  Can you provide a sample scaled down program that I can use to replicate the issue here?  You can put it in a zip file and send it to support@leadtools.com with my name in it and mention this post.

I used your code above and there weren't any errors thrown.  I made my own try-finally block (no catch blocks).  I commented out the sqlCmd statements, and the two if-statements for my test.  I called Startup() at the very beginning of the try block and Shutdown() in the finally block.  No issues.  I also put the whole try-finally block into a for-loop, and iterated it 5 times without any issues.  A sample program that throws the error on your end would be easier to replicate and debug here.

Thank You.
 
#3 Posted : Tuesday, October 2, 2007 10:57:16 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


The problem has disappeared -- which makes me a bit nervous but my experience tells me that it's not a LEAD issue.  I've played with it all day with no error.  Thanks for your response.
 
#4 Posted : Tuesday, October 2, 2007 12:28:46 PM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

"Attempted to read or write protected memory.  This is often an indication that other memory is corrupt." is thrown by the .NET Framework.  LEADTOOLS uses many .NET methods, so the error is indirectly thrown.  Most of the times it's when you don't call the Startup() method for any of our engines (RasterCodecs, RasterDocumentEngine, etc).  But since you were calling that, that couldn't have been an issue.  Next time it happens, I would say check the stack trace to see which method threw the exception.
 
#5 Posted : Friday, October 19, 2007 11:44:24 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


The problem persists and through some testing I have discovered some information that may assist in identifying what I'm missing.

The above code throws the exception for a subset of the *.jpg files with which I am testing.  The Leadtools.Codecs.cmp.dll is in the output folder as it should be.  The application does not throw an exception for any *.bmp files.  I'm wondering if the problem is with the bits per pixel somehow, but it seems to be image independent.  I have also noticed that one *.jpg that consistently produces the problem takes an unusually long time to load from the RasterOpenDialog, both in the preview window and then the OK button is activated.  Not all *.jpgs do that.  The troubeling *.jpg is not large at all, in fact it's only 146K whereas the same image but *.bmp is 9MB.  To make things even more interesting, the troubeling file opens fine in the Main 32-bit Demo and it saves to a file in *.cmp format just fine (I'm going to a memory stream) -- so I don't think the file is corrupt in any way.  In fact, other than the latency in my code it loads just fine.

What could cause one *.jpg to throw the exception and not another when saving it to a memory stream via RasterCodecs.Save()?

Thanks a lot for your time.
Matt

PS -- a snapshot of the stack can be emailed on request.  I tried posting a jpg and it wasn't readable, and a bitmap was too big.
 
#6 Posted : Monday, October 22, 2007 5:04:26 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

Not sure on why it would throw an exception on a memory stream.  Can you send the actual jpg file that's giving you trouble?  I can do some tests here with it.  You can send it to support@leadtools.com and mention this post, and I'll take a hold of that email.
 
#7 Posted : Tuesday, October 23, 2007 12:37:26 PM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


I have sent the image in question.  Other images throw an exception when saving to a MemoryStream, but none with the frequency of the image in question.  I have also considered that it may be in the acquisition phase of the image, so I am posting that code below as well.  The only thought I have against that hypothesis is that they always load into a RasterImage object just fine.  But it is a thought.

I really appreciate your time with this one.

Matt

         public void GetLeadtoolsImages()
        {
            RasterOpenDialog dialog = null;
            RasterCodecs codecs = null;
          
            RasterCodecs.Startup();
            codecs = new RasterCodecs();

            dialog = new RasterOpenDialog(codecs);
            dialog.DereferenceLinks = true;
            dialog.CheckFileExists = false;
            dialog.CheckPathExists = true;
            dialog.EnableSizing = true;
            dialog.Filter = new RasterOpenDialogLoadFormat[]
            {
                new RasterOpenDialogLoadFormat("Bitmap", "*.bmp"),
                new RasterOpenDialogLoadFormat("JPG", "*.jpg"),
                new RasterOpenDialogLoadFormat("LEAD", "*.cmp")
            };
            dialog.FilterIndex = 1;
            dialog.LoadFileImage = true;
            dialog.LoadOptions = false;
            dialog.LoadRotated = true;
            dialog.LoadCompressed = true;
            dialog.Multiselect = false;
            dialog.ShowGeneralOptions = true;
            dialog.ShowLoadCompressed = true;
            dialog.ShowLoadOptions = true;
            dialog.ShowLoadRotated = true;
            dialog.ShowMultipage = true;
            dialog.ShowPdfOptions = false;
            dialog.ShowPreview = true;
            dialog.ShowProgressive = true;
            dialog.ShowRasterOptions = true;
            dialog.ShowTotalPages = true;
            dialog.ShowDeletePage = true;
            dialog.ShowFileInformation = true;
            dialog.UseFileStamptoPreview = true;
            dialog.PreviewWindowVisible = true;
            dialog.GenerateThumbnail = false;
            dialog.Title = "IMPROVIS Open Image Dialog";
            dialog.FileName = string.Empty;

            if (dialog.ShowDialog(this.parent) == DialogResult.OK)
                // this will just generate other copies of the image via a RasterImage constructor
                ImageManipulator.GetLeadtoolsImages(this.imageView, dialog.OpenedFileData[0].Image);

            codecs.Dispose();
            RasterCodecs.Shutdown();
        }

 
#8 Posted : Wednesday, October 24, 2007 7:45:43 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

Hello Matt,

I ran your code above, no errors.  I also added a save statement that saves to the memory stream, and called it 500 times in a for-loop.  No errors thrown.  What does your save function look like saving to the memory?  Also can you post the code where you take the MemoryStream and insert in to the database?

Thanks.
 
#9 Posted : Monday, November 5, 2007 4:01:39 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


Forgive the long delay since my last post -- I'm working this application from many different angles.  But the priority to fix this problem has greatly increased.

My original post above contains my save code, and the exception is always thrown at RasterCodecs.Save(), so I don't think it has anything to do with my database.  I have done more testing my modifying the save code (above) to use the following:

                                codecs.Save(
                                    image.HighResolutionImage, stream, RasterImageFormat.Cmp,
                                    image.HighResolutionImage.BitsPerPixel);
and

                                codecs.Save(
                                    image.LowResolutionImage, stream, RasterImageFormat.Cmp,
                                    image.LowResolutionImage.BitsPerPixel);

because I was questioning whether hard-coding the 24 for BPP was causing the error.  It is not.

Furthermore, the problem seems not to be dependent on file types like I had originally supposed.  Our QA department is getting the exception with some BMPs and some JPGs, but not all.  My hope is to work this out and then upgrade to medical to save with lossless compression, but BMP and JPG is good enough for now.

I am using RasterPro for .NET, version 15.  We develop under .NET 2.0.

Thanks for continuing to assist me.  I really appreciate your time.

Matt
 
#10 Posted : Monday, November 5, 2007 6:54:47 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

Hi Matt,

Do you have a stack trace of that error?  Can you post it here?

Also, how big is your application?  I'd like to replicate it here with it, and see how it occurs.  Try to scale the app down as much as possible and then email it to me by replying to one of the emails that I sent you.  You can leave out the DLLs to keep the filesize small.

Thanks.
 
#11 Posted : Wednesday, November 7, 2007 5:44:25 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


I've done some more testing to try to uncover clues about this.  The stack trace is below:

A first chance exception of type 'System.NullReferenceException' occurred in Leadtools.dll
   at Leadtools.RasterImage.get_BitsPerPixel()
   at HzObj.Clinical.Series.SavePatientSeries(Patient patient) in C:\dev\HzSys\HzObj\Clinical\Series.cs:line 773

My program allows the entry of x-ray images from various sources -- this source is from a file.  I have a series object that contains one or more RasterImage objects that will be saved to the database.  I have set up a series with four images each obtained from a file.  When I try to save the series, the exception occurs on the first image of the series sometimes, sometimes the second, etc.  There's not a pattern that I can tell.

I have broken into the file input code and have verified that the BitsPerPixel property is properly set when I obtain my images (8), but when I brake into the RasterImage.Save() method before it executes, I can clearly see that the BitsPerPixel property is going to return a NullReferenceException.  I don't know what could cause that.

Because of the size of our application and company policies, I can't send you the executable without going through a lot of steps.  What I am in the process of doing is writing a small application that does this same thing (in fact I'm copying/pasting the code in most cases).  I can get that to you.

I have noticed behavior like this in the past when an object has its Dispose() method called, but I'm not doing that on any RasterImage.

As always, thanks for the help.

Matt
 
#12 Posted : Wednesday, November 7, 2007 6:14:19 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


The other exception that happens at the same location is as follows:

A first chance exception of type 'System.AccessViolationException' occurred in Leadtools.dll
   at L_MemoryCopy(Void* , Void* , UInt32 )
   at LT_Namespace.L_CopyMemory<unsigned char,unsigned char>(Byte* dest, Byte* src, UInt32 count)
   at L_GetBitmapRow(_BITMAPHANDLE* , Byte* , Int32 , UInt32 )
   at Leadtools.Internal.LtKrnExports.L_GetBitmapRow(Void* pBitmap, Byte* pBuffer, Int32 nRow, UInt32 uBytes)
   at L_GetBitmapRow(_BITMAPHANDLE* pBitmap, Byte* pBuffer, Int32 nRow, UInt32 uBytes)
   at fltSaveCMP(_SAVEDISPATCH* )
   at Leadtools.Codecs.Cmp.CmpCodec.fltSave(IntPtr dispatch)
   at ManagedFLTSAVE(Int32 fmt, _SAVEDISPATCH* dis)
   at L_SaveFile(Char* , _BITMAPHANDLE* , Int32 , Int32 , Int32 , UInt32 , IntPtr , Void* , _SAVEFILEOPTION* )
   at Leadtools.Codecs.RasterCodecs.SaveOnePage(Int32 page, SaveParams saveParams)
   at Leadtools.Codecs.RasterCodecs.DoSave(SaveParams saveParams)
   at Leadtools.Codecs.RasterCodecs.Save(RasterImage image, Stream stream, RasterImageFormat format, Int32 bitsPerPixel)
   at HzObj.Clinical.Series.SavePatientSeries(Patient patient) in C:\dev\HzSys\HzObj\Clinical\Series.cs:line 773

Notice that they originate from the same line.  Line 773 was included in my original post, but this is it:

                                codecs.Save(
                                    image.HighResolutionImage, stream, RasterImageFormat.Cmp,
                                    image.HighResolutionImage.BitsPerPixel);
Where stream is a .NET MemoryStream.

I just got this exception on an image (BMP) and turned around and loaded/saved it again and it worked.  Odd.

Thanks.
 
#13 Posted : Wednesday, November 7, 2007 7:50:24 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

That does seem odd.  Our Leadtools.dll wraps around our API and it seems to be happening at the API level.  I'm going to wait for your sample application and test it with that.  Make sure you add "Attn: Jigar" in the subject and the body of the message so that it comes to me.

Thanks.
 
#14 Posted : Wednesday, November 7, 2007 10:55:19 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


Jigar,

In the process of creating the sample application, I have come across a good clue.

First, I decided that the two exceptions are in fact different problems, and in all probability those problems came from the same source -- which is to say that I'm probably doing something in my code that's questionable at times and not others.  Following that line of thinking, I decided to tackle the "Attempted to read or write protected memory" exception and like your sample application, mine wasn't crashing.  I started adding more and more functionality and it didn't crash.  Eventually I decided that the problem wasn't with the MemoryStream at all, and that the protected memory was in fact the RasterImage.  I replace my call to RasterCodec.Save() with the following:

                                codecs.Save(
                                    new RasterImage(image.HighResolutionImage), stream, RasterImageFormat.Cmp,
                                    image.HighResolutionImage.BitsPerPixel);

And that did it.  I have saved many images with no exception.  That tells me that somewhere I'm doing something to HighResolutionImage that would lock if from a read into the MemoryStream object.  And sometimes it is locked and not others (I use the term "locked" loosely -- not in the traditional database locking way).  Assuming my hypothesis is correct, do you have any ideas as to what could cause the data of a RasterImage from being accessed?

The other issue is with multiple images being saved iteratively in the code.  Somehow I'm still getting the exception from accessing BitsPerPixel -- I'll continue with my sample application for that one too.

Thanks.
Matt
 
#15 Posted : Thursday, November 8, 2007 5:34:29 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


More information...

In more testing, I started suspecting that the crash was only on the HighResolutionImage (see my original post) and not the LowResolutionImage, so I switch the order in which they were saved to MemoryStreams.  This was an attempt to see if the the anomaly was related to a specific image and sure enough the exception was still thrown for the HighResolutionImage.  Given that, I started searching for how I handled the imaged differently through the capture-save process and there were two differences...1) I don't draw the high resolution image and 2) I don't resize it via ResizeCommand (I do both to the low resolution image).  As an experiment I decided to resize the high resolution image to its same size.  Sure enough, when I do that as the image is captured, no exception is thrown on save.

Of course that's a band-aid, but it's one that gives me information as to the problem.  For efficiency reasons I don't want to run the ResizeCommand action if I don't have to. 

Here is a copy of my image capture functionality with the new resizing that worked:

        public static void GetLeadtoolsImages(Series.ImageView imageView, Leadtools.RasterImage sourceImage)
        {
            // testing
            ResizeCommand command = new ResizeCommand();

            if ((imageView == null) || (sourceImage == null))
                return;

            //imageView.HighResolutionImage = sourceImage;  < this is the OpenedFileData[0].Image returned from RasterOpenDialog
            // this fixes the problem for some reason
            imageView.HighResolutionImage = new RasterImage(
                RasterMemoryFlags.Conventional,
                (int) (sourceImage.Width),
                (int) (sourceImage.Height),
                sourceImage.BitsPerPixel,
                sourceImage.Order,
                sourceImage.ViewPerspective,
                sourceImage.GetPalette(),
                IntPtr.Zero,
                0);
            command = new ResizeCommand();
            command.DestinationImage = imageView.HighResolutionImage;
            command.Flags = RasterSizeFlags.Bicubic;
            command.Run(sourceImage);

            imageView.OriginalPixelSize = new Size(
                imageView.HighResolutionImage.Width, imageView.HighResolutionImage.Height);

            ImageManipulator.GetOtherLeadtoolsImages(imageView);
            imageView.IsNew = true;
        }

So given the "Attempted to read or write..." exception is with reading the RasterImage and not the writing to the MemoryStream, what side effect of either 1) resizing or 2) saving a new image generated from the old one via the RasterImage(RasterImage) constructor (earlier post) is resetting the accessibility of the RasterImage?

Thanks again for your help on this.
Matt

By the way, that action seemed to fix the BitsPerPixel problem as well.

 
#16 Posted : Thursday, November 8, 2007 7:39:51 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

It's possible that the RasterImage is being locked for some reason.  Try to call the Release() method of the raster image object right before you call the save method, and see what it does.  You can comment out the resize command for the test.  One more thing to check would be the BitsPerPixel value before and after the Release() call, to see if it's being modified.  Also you can try locking the object for exclusive memory access by calling the Access() method and then immediately call Release(), so it just locks and unlocks the memory access for it.

If somehow the object gets locked and you try to call Access(), it should throw an error at that line, which means we have our answer, that somewhere it's being locked.  By the way, are you running this in a multi-threaded application or on a multi-core CPU?

I'm still going to ponder over this to see if there could be any other possibilities.
 
#17 Posted : Sunday, November 11, 2007 10:17:12 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


I ran the Release() test three successful times, but on the fourth time I got the "Attempted to..." exception.  I also tried the Access()/Release() combination and I still got the same exception.  No new information there.

But as I was testing I thought of a third way that I am handling the high resolution and low resolution images differently.  Recall that highResolutionImage is a copy of the original image in all its glory (size, etc.) whereas lowResolutionImage is just one sized down so that information retrieval over the network is minimized whenever possible.  The difference is that I obtain highResolutionImage from RasterOpenDialog whereas lowResolutionImage is created from highResolutionImage via RasterImage's copy constructor.  Better said, highResolutionImage is meerly a pointer to RasterOpenDialog.OpenFileData[0].Image property with MultiSelect set to false.

From that information, I decided not to use the Image property directly, but rather to create a new RasterImage with it via the RasterImage copy constructor.  I have run 20 tests with no exception being thrown (usually I get the exception after 4-8 tries).  We have an outstanding QA department and I'll get them started on it Monday if they're available, but I feel comfortable that this gives us more information.  Incidentally, this fix is the same as one of my previous band-aids where I was calling RasterCodec.Save() and using the copy constructor as the image to save (duplicating RasterOpenDialog's image).  My ResizeCommand band-aid fix effectively did the same thing since resizing is non-destructive.  The only flaw with this hypothesis is that the sample applications that save to a file behaved just fine.

If this is a sound theory, the net effect for me is that I have to generate another image, which is less than ideal but far more stable.  The cost is one of time since the garbage collector will get rid of RasterOpenDialog's RasterImage.

I am working on a multi-threaded application although I don't yet spin off any threads for any imaging functionality.  I'm sure that will come, but nothing yet.  I'm also on an old-fashioned (ha) single core.

Thanks again for your help.
Matt
 
#18 Posted : Monday, November 12, 2007 4:14:44 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

Hi Matt,

It makes sense that the reference to the RasterOpenDialog may be getting garbage collected after a certain amount of time, and causing the error to be thrown.  Instead of using the copy constructor, just do "RasterImage newImage = RasterOpenDialog.OpenFileData[0].Image.CloneAll()."  The CloneAll() method returns an exact copy of the object.  See if that makes it simpler and/or faster than the copy constructor.
 
#19 Posted : Monday, November 12, 2007 6:12:48 AM(UTC)

mbsiehs  
mbsiehs

Groups: Registered
Posts: 28


Jigar,

That's interesting -- I thought the garbage collector would not try to destroy anything if there was a reference pointing to it and the RasterImage object RasterOpenDialog.OpenFileData[0].Image did have a reference to it (highResolutionImage) even after the RasterOpenDialog gets destroyed.  I wonder if Dispose() is manually being called on the RasterImage when the RasterOpenDialog is being disposed of -- that would certainly cause the garbage collector to destroy it regardless of whether highResolutionImage refered to it or not.

Nevertheless, I'll consider this one solved.  Thanks so much for the time you have spent with me working through this.  You've gone above and beyond on this one.

Matt
 
#20 Posted : Monday, November 12, 2007 6:25:54 AM(UTC)

jigar  
Guest

Groups: Guests
Posts: 3,022

Was thanked: 2 time(s) in 2 post(s)

You're welcome.
 
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Powered by YAF.NET | YAF.NET © 2003-2024, Yet Another Forum.NET
This page was generated in 0.446 seconds.