I'm fighting an issue where my resized images looses color saturation when I manipulate them using GDI.
I'm loading an JPG as original, resize it and the resulting image has a lot less saturation (color intensity) than the original picture. What can I do to improve that? this is my code:
using ( var original = System.Drawing.Image.FromStream( new MemoryStream( image.RawData ) ) ) { using ( var dst = new Bitmap( width, height, PixelFormat.Format32bppArgb ) ) { using ( var g = Graphics.FromImage( dst ) ) { g.SmoothingMode = SmoothingMode.HighQuality; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.CompositingQuality = CompositingQuality.HighQuality; g.DrawImage( original, 0, 0, dst.Width, dst.Height ); g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.DrawImage( original, 0, 0, dst.Width, dst.Height ); var jpgEncoder = GetEncoder( ImageFormat.Jpeg ); var myEncoderParameters = new EncoderParameters( 1 ); var quality = 95; var myEncoderParameter = new EncoderParameter( Encoder.Quality, quality ); myEncoderParameters.Param[0] = myEncoderParameter; dst.Save( buffer, jpgEncoder, myEncoderParameters ); } } }
I've tried with different pixelformats, removing all filters etc but I always get the same result. Is this some known issue with GDI, or have I missed something?
Addon: When opening the image in Paint.NET, I get the same issue with low saturation, even without rescaling, so I guess it's the way GDI+ loads images (jpgs)?
This image was saved from photoshop with color profile sRGB, but afaik JPG doesn't have info about colorprofiles embedded. And even if it did, I believe that firefox doesn't obey them (which is what I've tested with)
More testing shows that it looks different in IE8 in contrast to firefox. JPGs seems to support color profiles, but most applications doesn't obey them. FF3.5 however, seems to do it. And it was Adobe RGB, not sRGB on the image.
I found the answer myself. It has to do with color-profiles not beeing applied by default in GDI+. Many people claims that you cannot automatically apply color-profiles using GDI, but apparently, the only change I needed to do was this:
using ( var original = System.Drawing.Image.FromStream( new MemoryStream( image.RawData ) ) )
to
using ( var original = new Bitmap( new MemoryStream( image.RawData ), true ) )
Apparently, Bitmap was a derived class of Image, and the constructor for Bitmap can take both a stream aswell as a boolean for "useIcm". That did the trick for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With