2

The questions in SO, for example this one or this one have discussed many reason for this exception, but none could help me to find out my problem, and I still cannot figure out why this is happening.

I'm having this error, when trying to save (code is below). And the strangest thing I've got is that - this error is occurring for random images (let's say "random" for now, because I don't know exact problem yet). Only for particular images, out of thousands, I got this problem.

Here is the one successful and one unsuccessful image when trying.

1. 2009-05-23_00.51.39.jpg

  • Image dimensions: 768x1024

  • Size: 87KB

  • Bit depth: 24

  • Color representation: sRGB

2. 2009-05-23_00.52.50.jpg

  • Image dimensions: 768x1024

  • Size: 335KB

  • Bit depth: 24

  • Color representation: sRGB

For image #1 the process is going smoothly, with no errors. However, for image #2, I keep getting this error. As you see the images are almost the same. Both are .jpg, same dimensions, and most of the properties are just same.

Here is the method.

public static Stream GetImageBytes(Stream fileStream, int maxWidth, int maxHeight, bool showCopyRight, string link, int fillColor = 0xFFFFFF) 
{
    var img = Image.FromStream(fileStream);

    if (maxHeight != 0 && img.Height > maxHeight)
        ResizeByHeight(ref img, maxHeight, fillColor.ToString("X6"));

    if (maxWidth != 0 && img.Width > maxWidth)
        ResizeByWidth(ref img, maxWidth, fillColor.ToString("X6"));

    if (showCopyRight)
        img = ApplyWatermark(ref img, "watermark.png", link);

    var ms = new MemoryStream();

    //problem is here
    img.Save(ms, ImageFormat.Jpeg);
    img.Dispose();
    return ms;
}

Edit after comments.

Ok, here is the Watermark method

private static Bitmap ApplyWatermark(ref Image img, string watermarkPathPng, string link) {
        const int x = 0;
        var y = img.Height - 20;
        string watermarkText;
        if (img.Width <= 220) {
            watermarkText = "shorter copy";
        } else {
            if (img.Width < 500)
                watermarkText = "longer copy";
            else
                watermarkText = "full copy  " + link;
        }
        var bp = new Bitmap(img);
        img.Dispose();
        using (var gr = Graphics.FromImage(bp)) {
            var watermark = Image.FromFile(watermarkPathPng);
            gr.DrawImage(watermark, x, y, watermark.Width, watermark.Height);
            watermark.Dispose();
            gr.DrawString(watermarkText, new Font(new FontFamily("Batang"), 13, FontStyle.Regular, GraphicsUnit.Pixel), Brushes.Black, 5, y + 5);
        }
        return bp;
    }

The reason why I've used Bitmap inside this method is that I had Indexed Pixels problem before and that solved the issue.

Community
  • 1
  • 1
Zafar
  • 3,394
  • 4
  • 28
  • 43
  • Can you include the code for `ApplyWatermark`, `ResizeByHeight`, and `ResizeByWidth`? The error might be from something you do to the image in one of those functions. – Scott Chamberlain Feb 01 '14 at 22:31
  • Let's keep it simple, please look at my comment for @Jason Williams answer. For exactly this example I've above, those methods are not being executed. – Zafar Feb 01 '14 at 22:34
  • What about `ShowCopyRight` is that being executed and are they the same for both with the same `link`? You don't mention that in your other comment. If `ShowCopyRight` is being run can you please show it? – Scott Chamberlain Feb 01 '14 at 22:37
  • yes. actually that methods is for images from old times. in old times, we had no copyright on images, but for new ones, we have copyright in build, so that doesn't hit much. the method execution is the same for both. none of the methods are being executed. – Zafar Feb 01 '14 at 22:39
  • i just kept those methods when posting question, to show why i need this method at all. – Zafar Feb 01 '14 at 22:40
  • 1
    The way you are handling `img` you don't need to use `ref` as you never replace `img` in the function. You could either return `void` and have your last line be `img = bp` or drop the `ref`, but that does not have anything to do with your problem. – Scott Chamberlain Feb 01 '14 at 23:21
  • Thanks for suggestion, I'll improve the code with this, once I found a solution for this particular problem. This is rolling my head for over 2 days actually. – Zafar Feb 01 '14 at 23:29
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/46614/discussion-between-zafar-and-scott-chamberlain) – Zafar Feb 01 '14 at 23:30

2 Answers2

1

Try copying the image rather than operating directly on the one you loaded. Often gdi errors are caused by you trying to change something that you think you "own" when the loader thinks it owns it.

As it only happens for some images, check the logic in your three processing methods - perhaps the failure only occurs if you need to do a vertical resize, in which case look for a bug in that method. Our maybe it's images that have to be processed by more than one of your methods.

It is also suspicious that you return img and pass it by reference in ApplyWatermark(). Check your logic here.

Jason Williams
  • 56,972
  • 11
  • 108
  • 137
  • Thanks. There are conditions exist that the `if` conditions are `true` and processing methods hit. However for both images above, #1 and #2, all the conditions are false and the processing methods are not being executes. There are many cases those will be executed, but for this particular example, they don't. – Zafar Feb 01 '14 at 22:30
  • in your edit, your watermarking function Disposes the image, and then when you return from that method you try to save the image which may no longer exist. Remove the ref on the img parameter. – Jason Williams Feb 02 '14 at 10:19
1

As I've not a great knowledge of GDI+, I'm not fully sure what has happened, but changing the following code line:

var ms = new MemoryStream();

//problem is here
img.Save(ms, ImageFormat.Jpeg);
img.Dispose();
return ms;

to this,

var ms = new MemoryStream();
var bit = new Bitmap(img);
img.Dispose();
bit.Save(ms, ImageFormat.Jpeg);
bit.Dispose();
return ms;

Worked well, so I just create a Bitmap from the image, then save the Bitmap to the Memory. Now this function is working well for all the images.

Zafar
  • 3,394
  • 4
  • 28
  • 43