0

I am using PHASH for computing the hash values for a large database of images. These images are of high resolution and hence I need to resize them for fast computing of the hash.

However, when I resize the image, the PHASH program throws an error. If I don't resize, the PHASH program works fine.

My resize code is as below.

public void ResizeImage(string ImagePath, int width, int height, string newPath)
    {
        Bitmap b = new Bitmap(width, height);
        using (Graphics g = Graphics.FromImage((Image)b))
        {
            FileStream fs = new FileStream(ImagePath, FileMode.Open);
            Image img = Image.FromStream(fs);
            g.DrawImage(img, 0, 0, width, height);
            fs.Close();
        }
        b.Save(newPath);
        b.Dispose();
    }

The error which I receive is "Attempted to read or write protected memory".

The phash code is as below:

 ph_dct_imagehash(imagePath, ref hash);

The above function calls the C++ program and returns me the hash value for that image. It works fine when the image is not resized programmatically. If I resize the image using MS Paint then also it works fine.

milan m
  • 2,164
  • 3
  • 26
  • 40
  • where is the phash code? – techno Jan 27 '14 at 05:31
  • Assuming you have checked that you save a valid resized image, here's a shot in the dark: When you cross the interop boundary to native code, you're exposed to premature garbage collection. Try adding `GC.KeepAlive(imagePath)` after your call to `ph_dct_imagehash`. – Roger Rowland Jan 27 '14 at 08:04

4 Answers4

0

You don't need a FileStream to open an Image You could just use Bitmap myBmp = Bitmap.FromFile("path");

Try removing the filestream.

techno
  • 6,100
  • 16
  • 86
  • 192
  • That was the first thing I did. A colleague suggested me to use FileStream so I used it. It doesn't work in both the cases. :-( – milan m Jan 27 '14 at 05:43
  • wait why do you use (Image)b when creating the graphics,just use b – techno Jan 27 '14 at 05:45
  • Tried removing the keyword "Image". Still the problem is not resolved. Still it is giving me the error "Attempted to read or write protected memory. This is often an indication that other memory is corrupt." – milan m Jan 27 '14 at 05:47
  • http://stackoverflow.com/questions/4074585/attempted-to-read-or-write-protected-memory-this-is-often-an-indication-that-ot – techno Jan 27 '14 at 05:49
  • Yeah. Still not able to resolve the issue. Its been more than 4 hours now. – milan m Jan 27 '14 at 07:56
0

The problem can be found in the call to ph_dct_imagehash. This calls unmanaged code and clearly there is an error in your interop between the managed and unmanaged realms.

The code in the question has no relevance to the problem. The solution will be to find and fix the problem with your use of ph_dct_imagehash.

We cannot offer any details on how to do that since you provided no details on ph_dct_imagehash.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

This is how I was able to resolve the answer.

public void ResizeImage(string ImagePath, int width, int height, string newPath)
{
    Bitmap b = new Bitmap(width, height);
    using (Graphics g = Graphics.FromImage((Image)b))
    {
        FileStream fs = new FileStream(ImagePath, FileMode.Open);
        Image img = Image.FromStream(fs);
        g.CompositingQuality = CompositingQuality.HighSpeed;
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.CompositingMode = CompositingMode.SourceCopy;
        g.DrawImage(img, 0, 0, width, height);
        fs.Close();
    }
    b.Save(newPath);
    b.Dispose();
}

I knew there was some problem with the resize function and not the ph_dct_imagehash function.

milan m
  • 2,164
  • 3
  • 26
  • 40
0

Got similar error doing almost exactly the same thing- creating a new bitmap from an existing one. Differences was that ours was a crop and instead of your safenative gdip line, our exception was in a different .net method in same class as yours: System.Drawing.SafeNativeMethods.Gdip.GdipDrawImageRectRectI in our case.

We were doing pretty much the same thing as you (copying a bitmap, although we cropped rather than resized it). Also we needed our bitmap in memory so we couldn't dispose of the final image, but otherwise it was same code as your original example.

Our solution was different. Even though our error was occuring post-copy in our crop stage, we used a 3rd party library that supplied the bitmap that was cropped.

To test if this was a windows issue or an issue with the library, wrote a new method to convert the original data (3 channel BGR byte data) into a BMP. This fixed the error.

Oddly, we had existing code that used the library's bitmap converter elsewhere w/no problems... The difference here was that the same image data was converted to a bitmap twice as part of a single processing run. If converted it once and cached/reused the handle rather than creating it twice in-line... this also fixed the problem.

Something to be aware of if you're using 3rd party code, it might be the culprit even if the stack trace shows it's .net.