CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Brendan Tompkins [MVP]

Blog First. Ask Questions Later.

Use GDI+ to Save Crystal-Clear GIF Images with .NET

In an effort to make our gate camera images visible on a ridiculously small cellphone screen,  I spent the past couple of days learning about the process of image Quantization.   GDI+ will allow you to take a full-color 32 bpp image and save it as a .gif file!  This turns out to be quite simple, and you can even re-size the image before saving it, by using the CreateThumnailImage method.

System.Drawing.Bitmap b = new System.Drawing.Bitmap(“c:\\original_image.gif“);
System.Drawing.Image thmbnail = b.GetThumbnailImage(100,75,
null,new IntPtr());
thmbnail.Save(“c:\\thumnail.gif“, System.Drawing.Imaging.ImageFormat.Gif);

“Cool!“ You're thinking to yourself, but don't think too soon.  You may be less-than-impressed by the dithery, grainy image produced by this technique.  Here's the output of this method with one of our gate camera images: 

So, what accounts for the grainy image?  It has to do with color quantization, sometimes called “palettization” or simply, the process of slapping a 256 color palette onto a full-color image, thereby reducing the total colors (and file-size).  The image is grainy because GDI+ by default uses the windows 256-color palette, and doesn't take into account the colors in the actual image.  When I found this out I went in search of a better color quantization technique for saving .GIF images... 

Personally I've found that almost all GIF images should be saved with an adaptive palette. These days, forget about the Web Palette, unless you're doing icons or big areas of solid color.  Most everyone will be running in at least 16K colors, and if by some small chance they're still running 256 colors, the browser will dither an adaptive image to a reasonable version anyhow.  An adaptive palette contains the 256 most frequently used colors in the image. Well, um sort of anyway. (As an aside, I tried to write my own “popularity palette” algorithm which used the most frequently used colors to build the palette, but my images looked worse than before!)  A good quantization algorithm also takes into account spacing between colors and stores colors that are, say blue and very-nearly-blue as one color, freeing up more space for colors that the eye sees as separate.  One such adaptive palette algorithm is called the “Octree“ algorithm.

I found two articles from Microsoft that helped out a great deal, KB 319061  and Optimizing Color Quantization for ASP.NET Images by Morgan Skinner at MS.  Morgan's article had some great code samples, and really useful base class which will allow you to plug in your own algorithm to quantize images. I ended up pulling bits and pieces of code from the two articles to create a library of objects used for creating Octree and Grayscale palettes.  Using the OctreeQuantizer object was easy, as you can see in this code snippet:

System.Drawing.Bitmap b = new System.Drawing.Bitmap(“c:\\original_image.gif“);
System.Drawing.Image thmbnail = b.GetThumbnailImage(100,75,
null,new IntPtr());
OctreeQuantizer quantizer =
new OctreeQuantizer ( 255 , 8 ) ;
using ( Bitmap quantized = quantizer.Quantize ( thmbnail ) )
{
     quantized.Save(“c:\\thumnail.gif“, System.Drawing.Imaging.ImageFormat.Gif);
}

OctreeQuantizer grayquantizer = new GrayscaleQuantizer ( ) ;
using ( Bitmap quantized = grayquantizer.Quantize ( thmbnail ) )
{
     quantized.Save(“c:\\thumnail.gif“, System.Drawing.Imaging.ImageFormat.Gif);
}

This code produced the following beautiful (In this case, beauty truly is in the eye of the guy who just spent three days trying to get it to work!) thumbnails, one with an adaptive palette, and one in grayscale. 

If you've got a cellphone with web capabilities, go to http://mobile.vit.org/ and see the image in all its 100 X 75 pixel glory.

UPDATE: 

See this post here for the latest version of this library

 

-Brendan

 



Comments

Brendan Tompkins said:

Not sure Paul. Are you opening my sln file directly?
# February 12, 2004 4:01 AM

Chrei Verdend said:

Please be patient - this is all new to me.

I am trying to create an aspx page, written in VB, that receives text from a form's input box, then generates a gif of the text and saves it to file. Everything is working fine except that the default halftone palette is terrible. I understand that the GIF needs to be color quantized to make it look decent and I believe that is exactly what your code does.

Problem is, I downloaded your project and have absolutely NO IDEA how to implement it into my apsx page. Your instructions say to "change the namespace and you've got your own adaptive image quantizer." Can you please explain how to do that, or point me in the right direction?

Also, is it going to be a problem that my aspx page is written in VB? If so, do I need to convert my code to C# to run your script? (I have no idea how to do that, but I could try.)

Otherwise, do you have any other suggestions for how I might get this accomplished?

Thanks for any and all help!!

# March 8, 2004 6:45 AM

Brendan Tompkins said:

Chrei... No problem. You can certainly use my assembly from VB.NET. That's the beauty of .NET IL! I built the dll for you, here's the download, with the PDB debug info too:

http://www.intrinsigo.com/bsblog/ImageQuantizationDll.zip

Drop this dll into your site's bin directory, and add a project reference to the DLL. You should then be able to create an instance of the ImageQuantizer from your aspx vb code, and call its Quantize method.

-Brendan
# March 8, 2004 7:18 AM

Brendan Tompkins said:

Sorry Chrei, you need to create an instance of the PaletteQuantizer object
# March 8, 2004 7:20 AM

Cheri Verdend (yes, I mistyped my name before) said:

Hi Brendan,

Thank you for responding so quickly! I'm trying to do what you told me to do... but I'm still a bit lost. (This is my first experience with .cs files, and I'm doing this in a text editor, not VS).

I've created an IIS virtual directory, in which I have a directory named "bin" (I hope that is all I need to do to create a bin directoy). In the bin directory I have saved the "ImageQuantization.dll" and the "ImageQuantization.pdb" files. I also saved my aspx file and all the files from your ImageQuantization.zip into the root of my virtual directory.

Below is the code for my aspx file. Right now it creates and saves a GIF with ugly colors. Would you please tell me exactly what code to insert and where to insert it to: add a project reference to the DLL and to create an instance of the PaletteQuantizer object.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
aspx code starts here
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System.Drawing"%>
<%@ Import Namespace="System.Drawing.Text"%>
<%@ Import Namespace="System.Drawing.Imaging"%>
<%@ Import Namespace="System.Drawing.Drawing2D"%>

<script language="VB" runat="server">

Sub Page_Load(sender As Object, e As EventArgs)
If Request("StringToDisplay")<>"" then
'Create the bitmap
Response.Clear( )
Dim objBitmap As New Bitmap(180,30, pixelformat.Format32bppArgb)
Dim objGraphic as Graphics = Graphics.FromImage(objBitmap)
objGraphic.Clear(Color.FromArgb(0, 255, 255, 255))
objGraphic.SmoothingMode = SmoothingMode.AntiAlias
objGraphic.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias
Dim textBrush As New SolidBrush(Color.FromArgb(255, 51, 0, 102))
Dim bgBrush As New SolidBrush(Color.white)
objGraphic.FillRectangle(bgBrush, 0, 0, 180, 30)
Dim objPoint As New PointF(0,0)
Dim objFont As New Font("Arial", 11, FontStyle.Bold)
objGraphic.DrawString(Request("StringToDisplay"), objFont, textBrush, objPoint)
'Save the image to file
objBitmap.Save(server.mappath("Image.gif"), System.Drawing.Imaging.ImageFormat.Gif)
objGraphic.Dispose( )
objBitmap.Dispose( )
End if
End Sub
</script>

<html><head><title>Text creation test</title></head><body><BR><BR>
<form method="POST" action="test.aspx">
String to write: <input type="text" name="StringToDisplay">
<input type="submit" value="Submit Text">
</form>
</BODY></html>

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

After several days of searching and searching for a solution, I feel like I'm very close. You are a life-saver. Thank you, again, for your help!

# March 8, 2004 9:49 AM

Brendan Tompkins said:

As to where to add this code... Try replacing this line of code from your original source with the above code:

objBitmap.Save(server.mappath("Image.gif"), System.Drawing.Imaging.ImageFormat.Gif)
# March 9, 2004 12:55 AM

Cheri Verdend said:

Brendan,

Ah! I finally got it working. Something was wrong with my .NET installation. Even though the dll was in the bin directory, I continued to get errors that that the namespace could not be found. After a myriad of false starts I finally uninstalled and reinstalled .NET - and now it works perfectly!

Thank you so much for your help!
# March 9, 2004 11:30 AM

Gary Peluso said:

Is there a way to set the transparent color? It defaults to black, but I need it to be white.

Thanks
# March 11, 2004 10:27 AM

Homam said:

Thanks! It's very useful.
Is there any way for quantization Jpeg images? I mean how can i save a jpeg image in a differrent quality?
# March 29, 2004 6:20 AM

Brendan Tompkins said:

Right. JPEG images aren't quantized, because each pixel's color value is mathematically determined, not taken from a palette. There's got to be a way to set the level of compression, which relates to image quality. Not sure how to do this, however...
# March 29, 2004 6:24 AM

Groves said:

Just wanted to thank you for your hard work. That library works like a charm -- I was having trouble with the standard ImageFormat.GIF exporting transparent, but yours works great.

Oh, and to Gary who'd asked about the transparency. If you haven't found it yet, try <b>MyImage.MakeTransparent(Color.White)</b>

Thanks, again,
Groves
# March 31, 2004 11:31 AM

Fred Thieme said:

Brendan

Thanks for the very useful color reduction code/dll. I came across your work while doing research for a pet project of mine. I was just gearing to do what you have already done I even read the same MSDN article that you site in your intro. I had your dll working in a VB test project in about 5 min. One Question -- Have you made any improvements or fixed any Bugs since posting the code and dll that I downloaded today 4/8/2004. Thanks again.

Fred
# April 8, 2004 10:15 AM

Brendan Tompkins said:

Fred,

What's out there is the latest. I'm not aware of any glaring bugs. I have the dll in production on a server and it seems to be chugging along.

-B
# April 8, 2004 12:39 PM

Fred Thieme said:

Great -- thanks for responding. I will plug it in and see how it goes.
# April 9, 2004 4:44 AM

Fred Thieme said:

Brendon:
Here is a method to set the transparent color for the gif file. First your dll optimizes the palette. Then before saving the file call the SetTransparentColor method on the optimized palette. The .NET Gif encoder will use the slightly modified palette to actually set the transparent color in the file. None of the color values are actually changed just the Alpha values. Check it out -- it works.

Private Sub ConvertToGif()
''load image to convert
Dim BMPQuantized As Bitmap
Dim BMPSource As Drawing.Image = Image.FromFile("C:\Ant.bmp")

''optimize the palette
Dim quantizer As New OctreeQuantizer(255, 8)
BMPQuantized = quantizer.Quantize(BMPSource)

''set the transpatent color where Color.Black is the desired transparent color
BMPQuantized.Palette = SetTransparentColor(BMPQuantized.Palette, 255, Color.Black)

''save as new .gif
BMPQuantized.Save("C:\AntConverted.gif", System.Drawing.Imaging.ImageFormat.Gif)
MsgBox("end")
End Sub

Private Function SetTransparentColor(ByRef SrcPal As ColorPalette, ByVal nColors As Integer, ByVal cT As Drawing.Color) As ColorPalette
''set the trans color in SrcPal
Dim i As Integer
Dim C As Drawing.Color
Dim Clrs() As Drawing.Color = SrcPal.Entries
For i = 0 To nColors
C = Clrs(i)
If (C.R = cT.R) And (C.G = cT.G) And (C.B = cT.B) Then ''match
SrcPal.Entries(i) = Color.FromArgb(0, C.R, C.G, C.B) ''trans
Else
SrcPal.Entries(i) = Color.FromArgb(255, C.R, C.G, C.B) ''opaic
End If
Next i
Return SrcPal
End Function


# April 9, 2004 10:11 AM

Tommaso said:

And if i want a optimized color reduced gif ?
# April 16, 2004 3:22 AM

Tommaso said:

eS: 16 color...
# April 16, 2004 3:26 AM

Brendan Tompkins said:

Well, I haven't poked around in the code in a while, but I think it's just a matter of overloading a method to pass in the bit depth you are looking for...
# April 16, 2004 3:30 AM

Herb said:

Brendan - Great work. Just came across your article while trying to fix this problem in outputting gifs, downloaded your dll, and five minutes later my gifs look beautiful. Thanks so much for your contribution.
# April 27, 2004 11:30 AM

Brendan Tompkins said:

Herb... Glad to have helped!

Brendan
# April 28, 2004 3:32 AM

Daniel said:

This class worked perfectly for me. I have a few classes that I always keep nearby because they are so damn good: ImageQuantizer is now one of them.

Thank you thank you thank you thank you ...
# April 29, 2004 12:51 AM

Brendan Tompkins said:

Glad to have helped Daniel. Good luck!

B
# April 29, 2004 2:05 AM

Linus Betschart said:

Hello

is it possible to save BMP Bitmaps with this class in 16 to 256 colours? With .net itself it's as I know not possible to save in different colour formats...

thx
LB
# May 11, 2004 12:38 AM

Jerry Spaeder said:

I downloaded the DLL you created for Cheri Verdend. Works great!

Thanks,
Jerry
# May 17, 2004 7:42 AM

Christoph Pecher said:

The quantization algorithm is not enough. I have problems with areas slowly changing color(gradients). I found an article concerning that issue, but no code that i cound translate to c-sharp. Anyone knows about how to implement the Error Diffusion Dithing in the second pass of the octree quantization? http://www.leptonica.com/applications.html#COLOR-QUANTIZATION
# June 3, 2004 6:07 AM

NatoCM said:

Brendan, thank you so much for your code. It worked just fine! Regards from Brazil!
# June 9, 2004 5:55 AM

Andrew said:

Great code, saved me from trying to do the same thing myself and wasting hours of time!
Thanks!
# June 24, 2004 3:09 PM

Avalon said:

Briliant.... there i was trying to work out a formual to correct the darkening of Png images in IE when i came across this little wonder code :) Life saver, Still need to fixteh png problem sometime though, Also does you code work with png transparency too... i ahve yet to test it.
# July 18, 2004 3:08 AM

darrel said:

THANK YOU! I spent the last couple of days searching for a way to fix the GIF saving problems. I finally stumbled across the Quantizer article on MSDN but that was a tad over my head to get working. That finally led your DLL which couldn't have been easier!

I'm rather amazed that the default GIF behaviour in .net is based on the windows pallet, but, then again, maybe it's not that surprising. ;o)

As for the person with the JPG question, you need to set the codec compression rate. Here's what I'm using (VB.NET):

====================

myImageCodecInfo = GetEncoderInfo("image/jpeg")
Dim myEncoderParameters As EncoderParameters = New EncoderParameters(1)
' this line sets the JPG compression quality
'(100 = best quality, 0 = most compression)
Dim myEncoderParameter As EncoderParameter = New EncoderParameter(myEncoder, 90)
myEncoderParameters.Param(0) = myEncoderParameter
imgOutput.Save([your path], myImageCodecInfo, myEncoderParameters)
imgOutput.Dispose()

========================
# July 20, 2004 4:41 AM

James said:

Brendan,
Lovely little library - thanks very much for posting this.

What is the difference between the PalleteQuantizer and the OctetQuantizer?
# September 5, 2004 3:58 PM

Ry said:

Quick and easy for me to use. Thanks for putting this out there for us!!!
# September 23, 2004 8:05 AM

Ian Kevan said:

Hi Brendan,

Thanks for the quantization code. I have the same problem as one of your other users in that when applying the Octree quantization to a captured windows XP form, because of the complex gradients in the title bar and toolbar, you end up with a very blocky looking graphic. Have you had any joy determining a way or applying error diffussion to the Octree quantization method?
# October 27, 2004 3:09 AM

Brendan Tompkins said:

Hi Ian,

I'm sorry to say that I haven't delved into other quantization methods since I first worked with this code. You should be able to plug a different quantizer in, however, if you find the algorithm out there somewhere.

Good luck.

Brendan
# October 27, 2004 3:18 AM

Ian Kevan said:

Tnaks Brendan, I will continue my search.
# October 27, 2004 10:51 PM

Ross Presser said:

Hi Brendan,

I've been working with you quantization code, and I have hit a most confusing problem.

On many images it works perfectly; but on this image, I am getting this exception:

Unhandled Exception: System.ArgumentException: '-169' is not a valid value for 'red'. 'red' should be greater than or equal to 0 and
less than or equal to 255.
at System.Drawing.Color.CheckByte(Int32 value, String name)
at System.Drawing.Color.FromArgb(Int32 alpha, Int32 red, Int32 green, Int32 blue)
at System.Drawing.Color.FromArgb(Int32 red, Int32 green, Int32 blue)
at ImageQuantization.OctreeNode.ConstructPalette(ArrayList palette, Int32& paletteIndex) in C:\Documents and Settings\btompkins\Desktop\ImageQuantization\OctreeQuantizer.cs:line 454

It's almost as if there is so much red in this image that the _red member (which was declared as an int) went negative?

I'll try isolating and maybe fixing this, but I'm not good with C#... I'll let you know what if anything I discover.
# November 9, 2004 8:28 AM

Brendan Tompkins said:

Man, that's strange. Looks like possibly the image is corrupt, and it's trying to read image data where it can't find any?
# November 9, 2004 8:32 AM

Ross Presser said:

I was right. Recompiling with /check+ and running my test case caused it to throw an arithmetic overflow exception in OctreeNode.Increment. I changed the definitions of _red, _green, _blue and _pixelcount from "int" to "ulong", and made this change to compensate, in OctreeNode.ConstructPalette:

// And set the color of the palette entry
palette.Add ( Color.FromArgb ( (int)(_red / _pixelCount) , (int)(_green / _pixelCount) , (int)(_blue / _pixelCount) ) ) ;

Now it works on all my images.

Thanks again for the code!
# November 9, 2004 8:47 AM

Ross Presser said:

Maybe this never cropped up before because I was just using larger images than you're used to. My images are 1500x1650 pixels; they're geographical maps that we put into trip routing books that you get from your auto club.
# November 9, 2004 8:49 AM

Brendan Tompkins said:

Ah... Cool. Can you send me the code that you updated, so that I can post it?

Thanks!
# November 9, 2004 8:50 AM

Ross Presser said:

Can't find an email address for you ... grab it at http: // www.imtek.com /images/updatedcode.zip [remove spaces to fix the deliberately broken link I typed]
# November 9, 2004 9:15 AM

Anthony Ruggeri said:

Great work on this library, it saved me a ton of time adapting an automatic graphics generator from using PNGs to GIFs due to a color interpretation bug in IE6. Let me know if you take any payments or contributions!
# November 16, 2004 2:47 AM

Brendan Tompkins said:

Nope. Thanks is plenty!
# November 16, 2004 2:51 AM

Ross Presser said:

Did you ever grab my updated code? If not, could you email your email address to me at rpresser AT imtek DOT com so I can mail it to you?
# November 23, 2004 2:18 AM

Pasquale Alfonso (aka)Bklynjava said:

Nice work, although I have numerous errors opening with C#.

Any advice is appreciated.
# December 8, 2004 3:23 PM

Hugo said:

Thanks and thanks again! I've been trying to find something like this for days!
# December 9, 2004 5:16 AM

Murray said:

Cool
But what if my hosting environment doesn't like unsafe code? is there a safe version?
I realise it may be slower, but it only runs infrequently as a batch job.

Cheers.
# December 13, 2004 3:27 PM

Brendan Tompkins said:

Murray, the unsafe is there so that we can pass a pointer to the quantizer ie (Color32* pixel) I'm not sure how to rework this in managed code without looking and getting into the details. You could try passing the Color32 by ref, and see where you get.

-Brendan
# December 14, 2004 1:08 AM

brendan - you're a star said:

thanks mate, just what i needed...and better than i was looking for.
# December 20, 2004 11:22 PM

Chris Lewis said:

...have been searching for some time for what you've done here - thanks a lot.
# January 11, 2005 1:30 AM

Doug Weems said:

Thanks Brendan,

This was very helpful. You are one of the good guys. :-)
# February 17, 2005 6:09 AM

John Hamm said:

I have modified the Quantizer class in that I can now pass the Quantize method a PixelFormt parameter so I can produce 4-bit images.

The problem, though, is that I think there is something odd going on in the OctreeQuantizer class - the bitmap that is produced has every other vertical row blank, and that widens the image, and cuts off half the image.

I think the problem may lie somewhere in FirstPass and SecondPass methods, I don't know enough about it to be sure though. Is traversing the pixels the same in a 4-bit image in memory as it is an 8-bit image?

Any ideas?
# March 4, 2005 12:58 AM

John Hamm said:

I meant to say "every other vertical column"
# March 4, 2005 12:59 AM

Brendan Tompkins said:

John,

Which Quantizer did you modify? The correct way to do this would have been to create a new class deriving from Quantizer called FourBitQuantizer or something, and then modify the QuantizePixel and InitialQuantizePixel methods.

I'm not surprized that it cut the image in half and only rendered every other line. Everything was based on 8 and you substitued 4!
# March 4, 2005 6:06 AM

Daniel said:

Is there a smart way to crop a created image, to eliminate all the space surrounding the rendered text?

"objGraphic.MeasureString(sText, objFont).Width" usually adds a lot of space, especially when using large font sizes. That extra margin causes rendered headlines to not line up well with body text.
# March 19, 2005 3:17 AM

.NET Tools Blog said:

# March 30, 2005 11:57 AM

Bill Oscott said:

Hi

This dll is cool, I had program running in VB.net that accessed its functions in 5mins. Thing is I would also like to use VB6 to access the dll. Is there anything I can do??

Thanks

Bill
# April 11, 2005 1:40 PM

Hubris Sonic said:

niiiiiiiiiiiiiiiice dude!
# April 28, 2005 4:13 AM

Max said:

Well done! I had little-to-no trouble implementing this into my system.

(What I want to know is why the current version of .NET doesn't already support this properly -- this seems like a common thing to do with graphics!)
# May 3, 2005 2:19 PM

Peter M said:

First of all, thanks very much for your efforts. This code was exactly what I've been looking for. :)

I'm using it to return gif images through the Response.OutputStream of an aspx page. The weird thing is that the transparency is working fine with some images and not with others although they all come from the same source.

Any thoughts would be greatly appreciated.
# May 12, 2005 9:08 AM

Ganesha said:

Thank you for the dll, my map image looks better now. Best regards from Jakarta.
# May 24, 2005 11:27 PM

Yukiko said:

I still not quite understand the whole thing and how to use it after downloading? Can someone please help me?
# June 6, 2005 6:57 PM

Dave said:

This is awesome. Just about to try to write my own version, found this site, five minutes later I have crystal clear images.

Thank you.
# June 7, 2005 3:54 AM

phil said:

Using Quantizer to reduce size of bitmap when saved to file. Works perfectly. Thanks.
# July 19, 2005 3:51 PM

srounsroun said:

Hi,

I'm working on gif files, the link for the dll doesn't work. Can someone could send me thte .zip file in my hotmail box ? thanks a lot, Hope this will resolve my optimization problem :)

here my hotmail box: srounsroun@msn.com

thanks

# August 18, 2005 5:55 AM

srounsroun said:

lol, sorry I found it on the zip file up there

check in bin/debug to get the DLL.


by all and thanks a lot
# August 18, 2005 6:54 AM

Brendan Tompkins said:

# August 18, 2005 3:54 PM

Bill said:

I've been working on my site to generate Hebrew characters and though I could force someone to download a font to view them, I wanted to dynamically generate the images. You're DLL is the best and got rid of those pesky "white" dots around the characters. Do you have the code in VB? Thanks,

Bill
# October 1, 2005 10:12 AM

Brendan Tompkins said:

I got the exciting news this week that a case study for one of the projects I've been working on has...
# February 23, 2006 10:47 AM

Brendan Tompkins said:

I got the exciting news this week that a case study for one of the projects I've been working on has...
# February 23, 2006 10:51 AM

Brendan Tompkins said:

I got the exciting news this week that a case study for one of the projects I've been working on has...
# February 23, 2006 11:21 AM

Brendan Tompkins said:

I got the exciting news this week that a case study for one of the projects I've been working on has...
# February 23, 2006 11:32 AM

Lee said:

Tried the original dll as well as this dll, all works beautifully on my machine locally, when I uploaded to my hosting, permission deneid. I'm guess the Quantizier is referencing system managed classes.. darn. what a shame.

really really loved this class.
# April 2, 2006 11:22 PM

Sebastian Krampe said:

Thanks for the classes, Brendan. They work great!

And Fred: Thanks to you for the transparent palette method.
Here's the version in c#:

ColorPalette SetTransparentColor(ColorPalette SrcPal, int nColors, System.Drawing.Color cT)
{
System.Drawing.Color C;
System.Drawing.Color[] Clrs = SrcPal.Entries;
for (int i = 0; i < nColors; i++)
{
C = ClrsIdea [I];
if (C.R == cT.R && C.G == cT.G && C.B == cT.B)
{
SrcPal.EntriesIdea [I] = Color.FromArgb(0, C.R, C.G, C.B);
}
else
{
SrcPal.EntriesIdea [I] = Color.FromArgb(255, C.R, C.G, C.B);
}
}
return SrcPal;
}

Regards
Sebastian
# April 3, 2006 5:56 AM

xuefeng yu said:

this is gread work!!!
thanks
# April 6, 2006 11:02 PM

Jimbob said:

Great stuff mate. I would have expected this to be part of GDI+ to be honest, as MS have done such a good job with the rest of it.

Thanks again.
# May 23, 2006 11:52 AM

Chris K said:

Hello, this stuff is awesome. Fortunatly I found this page, when this problem occured in my program.

What i wanted to ask: Is there any solution to save partly transparent (Opacity: 50%, or something like this) areas? pixels with alpha=255 are saved transparent, but when the alpha value is less then 255, these pixel are black!

Chris
# May 23, 2006 2:35 PM

Steve said:

Hello,

I really would like to be able to use you code but Im not sure if I can. So far I have an image being displayed using a .ashx file. This file basicaly gets an jpeg image from a database and makes it into a trnasparent gif but obviously the gif looks terrible.

Can I use your code? And if so how? I've never used a .dll file like this before.

Thanks in advance,
Steve
# June 9, 2006 4:14 AM

Will said:

Thanks a million.

Like many others here, I was reluctantly bracing myself to do battle with the MSDN code and you've saved me ages.

# September 25, 2006 6:30 AM

Ariel said:

Hi brendan, i congratulate you for your project.. i'm trying to use it but i can't make it work.. i'm creating dynamic images with text (drawstring with a Graphics), and i'm not sure where to use the quantizer, if i modify the bitmap before the "Graphics graph =Graphics.FromImage(bm)" it throws an exception liek this: "A Graphics object cannot be created from an image that has an indexed pixel format. ", if i put it after then it remains black at the end..

Just in case i post the function i made to create the Graphics:

public Graphics openGraph(ref Bitmap bm,string bgcolor)

{

        if(bgcolor=="Transparent")

        {

OctreeQuantizer quant=new OctreeQuantizer(255,8);

bm=quant.Quantize(bm);

        }

        Graphics graph = Graphics.FromImage(bm);

        graph.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;graph.InterpolationMode=System.Drawing.Drawing2D.InterpolationMode.Bilinear;

        graph.Clear(Color.FromName(bgcolor));

          return graph;

}

(i've already tried this one with it too:

"bm.MakeTransparent(Color.FromName(drpBackcolor.SelectedItem.Text));

bm.Save(......)")

but nothing..plz if someone can answer me, i'd appreciate that thx..(if you can, mail me plz to flesler@hotmail.com)

# October 8, 2006 8:49 PM

Ariel said:

I tried doing it at the end of the drawing, just before saving and it improves the quality, but no transparent background.. plz can some1 ask me as soon as possible? I really need it

# October 11, 2006 2:48 PM

Ariel said:

I tried doing it at the end of the drawing, just before saving and it improves the quality, but no transparent background.. plz can some1 ask me as soon as possible? I really need it

# October 11, 2006 2:48 PM

Sylvain Fasel said:

Hi,

thank you very much for this wonderful piece of code, seeminglessly integrated into my project.

For what I need it to do, it works perfectly, and the images are perfect.

So cool to share this freely!

Best regards.

# November 7, 2006 7:56 AM

Shaun Llewelyn said:

Thanks, I was getting grainy gifs. Worked a treat. Brilliant!

# November 9, 2006 9:34 AM

Barry said:

Hello.

***I am a newbie who needs help! ***

This looks like the perfect program I would need to convert a 256 color GIF that is located on my web server in a folder called temp, into a 16 color GIF.

After it is converted, I want to save it with the same name and path.

I have Visual Web Developer 2005 Express.

Please help me set this up.

I have no .aspx file yet.

(Also, I have no experience yet).

I will be coming from an asp page that has the filename in the url like my_page.asp?file_name=image_256.gif

I am used to vbscript, so I would get the filename with:

file_name= Request.QueryString("file_name")

I have placed all files (from the download above) in a web folder called gif_16

Any help to figure this out would be appreciated.

Thanks in advance!!!

Barry in Ottawa, CANADA.

# December 4, 2006 7:02 PM

Brendan Tompkins said:

Barry,

The quantizer code should produce a 16-color gif using the following command:

OctreeQuantizer quantizer = new OctreeQuantizer ( 15 , 4 ) ;

# December 5, 2006 8:02 AM

Barry said:

Hey Brendan. It has been snowing here in CANADA. Looks like it isn't  there!

Thanks for the reply!!

That's great that the code can do it!!

Which lines of code are required to do what I want?

Can you help me set it up?

I see some lines at the top starting with:

System.Drawing.Bitmap b = new System.Drawing.Bitmap(“c:\\original_image.gif“);

I also downloaded your project, do I need it all?

Is there an aspx page missing?

Which files/folders do I need to upload to my web server to get this to work?

I'm a slow newbie.

Please help.

Barry

# December 5, 2006 12:35 PM

Brendan Tompkins said:

A while back, I posed a solution for creating an adaptive GIF image from a JPEG image source in .NET,

# December 8, 2006 8:43 AM

Tuan Nguyen said:

can anyone please post the safe managed Code for this?

# December 15, 2006 3:18 PM

Anonymous said:

this guy is selling component based on OctreeQuantizer.cs

http://www.amarantin.se/

# January 11, 2007 10:35 AM

Manso said:

Hi,

Thanks for an excellent component.

We're trying to use it in a medium trust environment, does anyone have any experience in how to make it work? We are getting "PolicyException: Required permissions cannot be acquired.", can someone provide us with some hints if/how we can make this work?

Many thanks,

Manso

# January 15, 2007 4:16 AM

James Maeding said:

Dang, best code I have seen for images with .net so far.

I am killing myself with IMageMagick and other command line progs, and no one seems to make it easy to make good images from 24 bit to 8 bit optimized palette.

This was just what I needed.

# January 18, 2007 12:34 PM

James Maeding said:

I just read the previous comments and am wondeeing if the code and dll that we can download, have all the fixes in them?

There was the definitions of _red, _green, _blue and _pixelcount from "int" to "ulong",

as well as the Transparent palette code (bug or feature?...).

Also, I open the code in VS2005 and it gives errors on build. It says:

Unsafe code may only appear if compiling with /unsafe.

I assume I need to add a flag somewhere to fix that, I think the orig code was from VS2003, and VS2005 wants a flag...

thanks

# January 18, 2007 12:59 PM

James Maeding said:

ok, had to check the allow unsafe code in build options,

also added suggested changes myself except for transparent option.

If anyone had improved things, please post :)

# January 18, 2007 1:53 PM

Allan The Dane said:

Preserving Transparency?

I'm converting a transparent Gif to grayscale using you code. But the transparency seems to be lost during conversion. Is there any way to preserve the transparency in the new image? I'm using the following code, which is basically just a conversion from your C# code to VB:

Dim objBitmap As New Bitmap("Transparent.Gif")

Dim objNewThumb As Drawing.Image = objBitmap.GetThumbnailImage(objBitmap.Width, objBitmap.Height, Nothing, New IntPtr())

Dim objGrayQuantizer As New GrayscaleQuantizer()

With objGrayQuantizer.Quantize(objNewThumb)

  .Save("GrayNoSoTransparent.gif")

End With

Any advice would be appreciated.

BTW - Great work! :)

Allan From Denmark

# January 18, 2007 2:49 PM

Justin Wignall said:

Three years later and still really useful! Great stuff Brendan, Thanks!

# January 19, 2007 8:08 AM

James Maeding said:

there was code to modify the palette posted by Fred Thieme, see previous posts.

I am currently figuring out how to plug that into things, I am a bit new at the .net objects.  I'll post it when I figure it out.

# January 19, 2007 2:02 PM