This is a long-standing bug in the .NET framework itself that I don't expect to see fixed any time soon. There are several related bugs I've also come across that throw the 'generic error occurred in GDI+' including if you access the PropertyItem collection for some JPEGs (to examine the EXIF codes) then from that point on you won't be able to save the image. Also, for no rhyme or reason some JPEGs, like the one you have here, simply won't save at all. Note that just saving as a different format won't always work either, although it does in this case.
The workaround I've employed in an app of mine that consumes pictures from all over the web (and therefore sees more than its fair share of these types of problems) is to catch the ExternalException and copy the image into a new Bitmap as in one of the previous answers, however simply saving this as a new JPEG will drop the quality rather a lot so I use code much like that below to keep the quality high:
namespace ImageConversionTest
{
using System.Drawing;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using System.Globalization;
class Program
{
static void Main( string[] args )
{
using( Image im = Image.FromFile( @"C:\20128X.jpg" ) )
{
string saveAs = @"C:\output.jpg";
EncoderParameters encoderParams = null;
ImageCodecInfo codec = GetEncoderInfo( "image/jpeg" );
if( codec != null )
{
int quality = 100; // highest quality
EncoderParameter qualityParam = new EncoderParameter(
System.Drawing.Imaging.Encoder.Quality, quality );
encoderParams = new EncoderParameters( 1 );
encoderParams.Param[0] = qualityParam;
}
try
{
if( encoderParams != null )
{
im.Save( saveAs, codec, encoderParams );
}
else
{
im.Save( saveAs, ImageFormat.Jpeg );
}
}
catch( ExternalException )
{
// copy and save separately
using( Image temp = new Bitmap( im ) )
{
if( encoderParams != null )
{
temp.Save( saveAs, codec, encoderParams );
}
else
{
temp.Save( saveAs, ImageFormat.Jpeg );
}
}
}
}
}
private static ImageCodecInfo GetEncoderInfo( string mimeType )
{
// Get image codecs for all image formats
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();
// Find the correct image codec
foreach( ImageCodecInfo codec in codecs )
{
if( string.Compare( codec.MimeType, mimeType, true, CultureInfo.InvariantCulture ) == 0 )
{
return codec;
}
}
return null;
}
}
}
Note that you'll lose the EXIF information but I'll leave that for now (you'll generally still be able to read the EXIF codes, even when saving the source image fails). I have long since given up attempting to figure out what it is that .NET doesn't like about particular images (and have samples of various failure cases should anybody ever want to take up the challenge) but the approach above works, which is nice.