I've tried half a dozen different techniques to resize a gif and maintain it's transparency
The current function looks like this
public static byte[] ResizeNoCrop(byte[] image, int width, int height)
{
byte[] buffer2;
if (image == null)
{
return null;
}
if (width < 1)
{
throw new ArgumentException("The minimum permitted image width is one pixel.", "width");
}
if (height < 1)
{
throw new ArgumentException("The minimum permitted image height is one pixel.", "height");
}
using (MemoryStream stream = new MemoryStream())
{
stream.Write(image, 0, image.Length);
stream.Position = 0L;
using (Image image2 = Image.FromStream(stream, true, true))
{
decimal num = (decimal)width / image2.Width;
decimal num2 = (decimal)height / image2.Height;
decimal num3 = Math.Min(num, num2);
int num4 = (int)Math.Min(Math.Round((decimal)(image2.Width * num3)), 2147483647M);
int num5 = (int)Math.Min(Math.Round((decimal)(image2.Height * num3)), 2147483647M);
using (Bitmap bitmap = new Bitmap(num4, num5, image2.PixelFormat))
{
byte[] buffer;
bitmap.SetResolution(image2.HorizontalResolution, image2.VerticalResolution);
bitmap.MakeTransparent(Color.Black);
using (Graphics graphics = Graphics.FromImage(bitmap))
{
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.DrawImage(image2, 0, 0, num4, num5);
}
using (MemoryStream stream2 = new MemoryStream())
{
ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
EncoderParameters encoderParams = new EncoderParameters(1);
encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, 0x5fL);
bitmap.Save(stream2, imageEncoders[1], encoderParams);
stream2.Position = 0L;
int count = (int)Math.Min(stream2.Length, 0x7fffffffL);
buffer = new byte[count];
stream2.Read(buffer, 0, count);
stream2.Close();
}
buffer2 = buffer;
}
}
}
return buffer2;
}
But I keep getting an image with a black background...which is infuriating since the images I am resizing are drawn in black over a transparent background.
The problem is that GDI+ doesn't have very good support for indexed images, such as GIF. The main problems are that you can not use a Graphics object on a indexed image, and you have very limited control over the color palette. In you example above, GDI+
is converting the indexed GIF into a 32-bit RGB image. It is then performing the graphics manipulation and then converting the image back into an indexed GIF. However, the transparent color is not retained in the conversion. Because it is working with the
image as a 32-bit RGB image, it ignores your attempt to set the color palette.
Here are a couple of links that talk about the issue and give a work-around for it. I personally like the first link best because it does not use unsafe code blocks.
Thanks, I had actually just come to fully undertand what was going on in the past few hours and had read those two links and written something that is fairly decent. I am going to check out the first link though as I hadn't seen it, and see if I can improve
upon my code.
MS actually has a bit of usefull reading on the topic too, related to colour matching
Member
496 Points
219 Posts
Resizing GIFs and maintaining transparency
Dec 19, 2008 01:05 PM|gibble|LINK
I've tried half a dozen different techniques to resize a gif and maintain it's transparency
The current function looks like this
But I keep getting an image with a black background...which is infuriating since the images I am resizing are drawn in black over a transparent background.
I can NOT change to png.
I also NEED to maintain the transparency
Has anybody done this successfully?
Thanks for any help provided :)
Member
496 Points
219 Posts
Re: Resizing GIFs and maintaining transparency
Dec 19, 2008 04:45 PM|gibble|LINK
I've now got the following code, resizing and saving the incoming gif bytes to a png and a gif
The png is perfect, the gif is just a black square.
These gifs are two colours, one colour black, one colour transparent or so the source.Palette shows. My guess is this is part of the problem?
1 Image source = Image.FromStream(new MemoryStream(imageBytes));
82 byte[] pngBytes = new byte[] { };
3 decimal wR = (decimal)width / source.Width;
4 decimal hR = (decimal)height / source.Height;
5 decimal r = Math.Min(wR,hR);
6 width = (int)Math.Min(Math.Round((decimal)(source.Width * r)), 2147483647M);
7 height = (int)Math.Min(Math.Round((decimal)(source.Height * r)), 2147483647M);
9 using (Bitmap oBmp = new Bitmap(width, height))
10 {
11 oBmp.Palette = source.Palette;
12
13 using (Graphics g = Graphics.FromImage(oBmp))
14 {
15 g.CompositingQuality = CompositingQuality.HighQuality;
16 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
17 g.PixelOffsetMode = PixelOffsetMode.HighQuality;
18 g.SmoothingMode = SmoothingMode.HighQuality;
19
20 g.Clear(Color.Transparent);
21 g.DrawImage(source, 0, 0, oBmp.Width, oBmp.Height);
22 }
23
24 // Save
25 string resizedFileName = "image.png";
26 try
27 {
28 oBmp.Save(Path.Combine(copyToPath, resizedFileName), ImageFormat.Png);
29 oBmp.Save(Path.Combine(copyToPath, resizedFileName.Replace(".png", ".gif")), ImageFormat.Gif);
30 }
31 catch (Exception x)
32 {
33 // ReportError
34 continue;
35 }
36 }
Member
496 Points
219 Posts
Re: Resizing GIFs and maintaining transparency
Dec 22, 2008 09:58 AM|gibble|LINK
Nobody?
Participant
1993 Points
438 Posts
Re: Resizing GIFs and maintaining transparency
Dec 22, 2008 11:53 AM|Benners_J|LINK
The problem is that GDI+ doesn't have very good support for indexed images, such as GIF. The main problems are that you can not use a Graphics object on a indexed image, and you have very limited control over the color palette. In you example above, GDI+ is converting the indexed GIF into a 32-bit RGB image. It is then performing the graphics manipulation and then converting the image back into an indexed GIF. However, the transparent color is not retained in the conversion. Because it is working with the image as a 32-bit RGB image, it ignores your attempt to set the color palette.
Here are a couple of links that talk about the issue and give a work-around for it. I personally like the first link best because it does not use unsafe code blocks.
http://ewbi.blogs.com/develops/2005/08/sparklines_22.html
http://www.bobpowell.net/giftransparency.htm
http://support.microsoft.com/kb/319061
Good Luck!
Member
496 Points
219 Posts
Re: Resizing GIFs and maintaining transparency
Dec 22, 2008 03:46 PM|gibble|LINK
Thanks, I had actually just come to fully undertand what was going on in the past few hours and had read those two links and written something that is fairly decent. I am going to check out the first link though as I hadn't seen it, and see if I can improve upon my code.
MS actually has a bit of usefull reading on the topic too, related to colour matching
http://msdn.microsoft.com/en-us/library/aa479306.aspx