Gif Color Indexing in ashx

  • Thread starter Thread starter macap.usenet
  • Start date Start date
M

macap.usenet

Hello,


I am creating Gif-Images (8bit: 256 colors) with using the
IHttpHandler and .ashx-Files.

My ProcessRequest-Method looks like this:

public void ProcessRequest(HttpContext context)
{
object o = context.Request["roomId"];
if (o == null)
{
// MP[TODO] ???throw exception???
context.Response.Write("No room found");
context.Response.End();
return;
}
Bitmap bmp = CreateUpcomingDaysImage();
context.Response.ContentType = "image/gif";

bmp.Save(context.Response.OutputStream, ImageFormat.Gif);
bmp.Dispose();
}



But the resulting Gif-Image has Dithering (http://en.wikipedia.org/
wiki/Dithering),
although I only use 2 grey-colors at the moment:




private Bitmap CreateUpcomingDaysImage()
{
Bitmap bmp = new Bitmap(_imageWidth, _imageHeight);
Graphics g = Graphics.FromImage(bmp);
SolidBrush evenCaptionColor = new
SolidBrush(Color.FromArgb(210, 210, 210));
SolidBrush oddCaptionColor = new
SolidBrush(Color.FromArgb(140, 140, 140));

RectangleF rect = new RectangleF();

for (int i = 0; i < _hoursOfDay; i++)
{
rect = new RectangleF(i * _pixel, 0.0F, _pixel,
_pixel);
if (i % 2 == 0)
g.FillRectangle(evenCaptionColor, rect);
else
g.FillRectangle(oddCaptionColor, rect);
}
g.Dispose();

return bmp;
}


Is there a way to avoid Dithering? I am not very sure, but I think
there is a technology
called "indexed colors" in Gif-Files so that the gif file can use 256
different spezified colors.
Can I use this to with the GDI+ Library of .NET? Or what else can I
do?


Regards,

Martin
 
But the resulting Gif-Image has Dithering (http://en.wikipedia.org/
wiki/Dithering),
although I only use 2 grey-colors at the moment:




private Bitmap CreateUpcomingDaysImage()
{
Bitmap bmp = new Bitmap(_imageWidth, _imageHeight);

For starters, you should use the Bitmap constructor that takes a third
PixelFormat argument, and pass Format8bppIndexed to it (though if you're
only using 2 colors, Format1bppIndexed might be even better).

After that, Bitmap (or rather, Image, from which it derives) has property
Palette. Before you draw onto the bitmap, you should fill that Palette with
all colors that you intend to use, e.g.:

bmp.Palette.Entries[0] = Color.FromArgb(210, 210, 210);
bmp.Palette.Entries[1] = Color.FromArgb(140, 140, 140);

That should do the trick.
 
One word of warning:
http://msdn.microsoft.com/en-us/library/system.drawing.aspx

"Caution:
Classes within the System.Drawing namespace are not supported for use
within a Windows or ASP.NET service. Attempting to use these classes
from within one of these application types may produce unexpected
problems, such as diminished service performance and run-time exceptions."

Marc
 
Marc Gravell said:
One word of warning:
http://msdn.microsoft.com/en-us/library/system.drawing.aspx

"Caution:
Classes within the System.Drawing namespace are not supported for use
within a Windows or ASP.NET service. Attempting to use these classes from
within one of these application types may produce unexpected problems,
such as diminished service performance and run-time exceptions."

Indeed, and there are good reasons for that as well:

http://blogs.msdn.com/tom/archive/2008/03/19/gdi-gdiplus-and-asp-net.aspx
http://blogs.msdn.com/carloc/archiv...et-alas-dgi-not-supported-from-a-service.aspx

All in all, it works, you just have to be extra careful with resource
allocation - a missed Dispose() call prove to be very expensive indeed!
 
Hello Pavel,

thank you very much. This sounds like it is what I wanted
For starters, you should use the Bitmap constructor that takes a third
PixelFormat argument, and pass Format8bppIndexed to it (though if you're
only using 2 colors, Format1bppIndexed might be even better).

After that, Bitmap (or rather, Image, from which it derives) has property
Palette. Before you draw onto the bitmap, you should fill that Palette with
all colors that you intend to use, [...]

But there is another problem now:

Bitmap bmp = new Bitmap(_imageWidth, _imageHeight,
PixelFormat.Format4bppIndexed);
bmp.Palette.Entries[0] = _colorBookedTime;
bmp.Palette.Entries[1] = _colorFreeTime;
bmp.Palette.Entries[2] = _colorPendingTime;
bmp.Palette.Entries[3] = _colorPrePostTime;
Graphics g = Graphics.FromImage(bmp);

This code throws an exception, because I cannot create a Graphics-
Object out of an indexed PixelFormat.

Is there a workaround to do it?

A short google survey says that many people are having this problem
and that there seems to be a very easy solution.
The solutions I found use unsafe code in C# with pointers and so
on ....

Isn´t there really an easy solution to get an indexed bitmap into a
Graphics object?

If there are other solutions... I do need a Graphics object urgently.
I only want to draw rectangles into the indexed bitmap.
If I can do it in another way... it would be fine too.


Regards,
Martin
 
But there is another problem now:

Bitmap bmp = new Bitmap(_imageWidth, _imageHeight,
PixelFormat.Format4bppIndexed);
bmp.Palette.Entries[0] = _colorBookedTime;
bmp.Palette.Entries[1] = _colorFreeTime;
bmp.Palette.Entries[2] = _colorPendingTime;
bmp.Palette.Entries[3] = _colorPrePostTime;
Graphics g = Graphics.FromImage(bmp);

This code throws an exception, because I cannot create a Graphics-
Object out of an indexed PixelFormat.

Is there a workaround to do it?

None that I know of. You'll have to use LockBits.
A short google survey says that many people are having this problem
and that there seems to be a very easy solution.
The solutions I found use unsafe code in C# with pointers and so
on ....

Isn´t there really an easy solution to get an indexed bitmap into a
Graphics object?

If there are other solutions... I do need a Graphics object urgently.
I only want to draw rectangles into the indexed bitmap.
If I can do it in another way... it would be fine too.

For one thing, if you only need to draw rectangles, then it's not hard
to do that with direct blitting via LockBits.

If you need something more complicated, then consider drawing to a
usual 32-bit Bitmap via Graphics, and then blitting from it to your
own indexed bitmap, looking up colors in the palette as you go.
 
Back
Top