Re: Finding nearest color of a predefined palette

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Jerad Rose (no_at_spam.com)
Date: 01/24/05

  • Next message: Daniel: "PrintPreviewDialog doesn't show any margin"
    Date: Mon, 24 Jan 2005 16:53:06 -0500
    
    

    Wow, I think I just found exactly what I was looking for.

    I continued checking out your other FAQs, and ran across your FAQ on
    "Creating an optimized palette for GIF images", which led me to this MSDN
    article:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/colorquant.asp

    There it shows me how to determine the "distance" between two colors --
    which I see now is just the sum of each RGB difference sqaured:

            Dim redDistance As Integer = OriginalColor.R - clr.R
            Dim greenDistance As Integer = OriginalColor.G - clr.G
            Dim blueDistance As Integer = OriginalColor.B - clr.B

            Dim distance = _
                    (redDistance * redDistance) + _
                    (greenDistance * greenDistance) + _
                    (blueDistance * blueDistance)

    Now, after realizing I can't use SetPixel on an indexed bitmap, I'm back to
    having to use the LockBits method in this article:

    http://support.microsoft.com/default.aspx?scid=kb;en-us;319591

    Wow. This seems like a lot of work for something that you would think
    simple. At any rate, I'm about there, and I'm happy.

    Thanks again, and hope this helps others that may run into this.

    Jerad

    "Jerad Rose" <no@spam.com> wrote in message
    news:uOwibOlAFHA.3820@TK2MSFTNGP11.phx.gbl...
    > Ok Bob (or whoever else could help), quick question.
    >
    > It looks like, in your FAQ (Creating Transparent GIF Images), you're using
    > the same source and destination palettes, with the exception that you
    choose
    > and set the index for the transparent color.
    >
    > So, while it looks like I can use your example to transfer the source
    image
    > (that can be any format, size, and color depth) to the destination image
    > (which will be 32x32, indexed 4bpp [16-color]), I still am not sure how to
    > do the color transformation, finding the nearest match from the 16-color
    > palette. I'm not even concerned about saving the file (these images will
    > not be saved as files, but rather into a database as a 1024 string of hex
    > characters representing the palette indexes). I'm just trying to figure
    out
    > how to do the color tranformation from a 32bpp color depth, to a 4bpp
    color
    > depth w/ a predefined palette.
    >
    > For example, I need something like this:
    >
    > --------------------------------------------------------------------------

    --
    > -------------
    >     Function CopyPixelsIntoNewPalette( _
    >             ByVal SourceImage As Bitmap, _
    >             ByVal NewPalette As ColorPalette) As Bitmap
    >         Dim x As Integer, y As Integer
    >
    >         Dim bmp As Bitmap = New Bitmap(32, 32,
    > PixelFormat.Format4bppIndexed)
    >         Dim clrClosestMatch As Color
    >
    >         For x = 0 To 31
    >             For y = 0 To 31
    >                 clrClosestMatch = FindNearestMatchInPalette(NewPalette,
    > SourceImage.GetPixel(x, y))
    >                 bmp.SetPixel(x, y, clrClosestMatch)
    >             Next
    >         Next
    >     End Function
    >
    >     Function FindNearestMatchInPalette( _
    >             ByVal SourcePalette As ColorPalette, _
    >             ByVal OriginalColor As Color) As Color
    >         Dim clr As Color
    >         Dim ClosestColor As Color
    >
    >         For Each clr In SourcePalette.Entries
    >             If DifferenceBetweenColors(clr, OriginalColor) < _
    >                     DifferenceBetweenColors(ClosestColor, OriginalColor)
    > Then
    >                 ClosestColor = clr
    >             End If
    >         Next
    >     End Function
    >
    >     Function DifferenceBetweenColors(ByVal clr, ByVal OriginalColor) As
    Long
    >         ' Some code here to calculate how close one color is to another
    >     End Function
    > --------------------------------------------------------------------------
    --
    > -------------
    >
    > But figuring out the algorithm for comparing colors and determining which
    > color is a closest match is what I can't figure out.
    >
    > Maybe I'm just totally missing something here.  Like, is one of your
    > examples doing the work for me (saving the file w/ a new palette
    > automatically sets each pixel to the closest match for the palette)?  If
    so,
    > that would be great too.  But if I have to do the work of matching an
    > arbitrary color to one of 16 colors in a palette, then that's what I'm
    > trying to figure out.
    >
    > Thanks again for your help -- it's much appreciated.
    >
    > Jerad
    >
    >
    > "Jerad Rose" <no@spam.com> wrote in message
    > news:uA568hiAFHA.4044@TK2MSFTNGP10.phx.gbl...
    > > Thanks Bob for your response.
    > >
    > > I will be checking out your site, starting w/ the GDI+ Beginners Guide,
    > > since I still feel fairly new at all this.  I'm typically a business
    > > developer and have not had much exposure to the graphical side of
    .NET -- 
    > > though, I'm enjoying it quite a bit.
    > >
    > > If you don't mind, keep an eye on this thread over the next week or so,
    so
    > > that I may hit you up w/ other questions I may have after reading the
    > guides
    > > you suggested.
    > >
    > > Thanks again for your help.
    > >
    > > Jerad
    > >
    > > "Bob Powell [MVP]" <bob@_spamkiller_bobpowell.net> wrote in message
    > > news:uC1nVtgAFHA.3824@TK2MSFTNGP10.phx.gbl...
    > > > There is an article in the GDI+ FAQ that explains how to modify the
    > > > transparent colour in a palette. This shows you how to alter the
    palette
    > > in
    > > > any 8 bpp image. You should be able to adapt this for your needs.
    There
    > is
    > > > also an article on LockBits that explains how that works if you're
    > > > interested.
    > > >
    > > > -- 
    > > > Bob Powell [MVP]
    > > > Visual C#, System.Drawing
    > > >
    > > > Find great Windows Forms articles in Windows Forms Tips and Tricks
    > > > http://www.bobpowell.net/tipstricks.htm
    > > >
    > > > Answer those GDI+ questions with the GDI+ FAQ
    > > > http://www.bobpowell.net/faqmain.htm
    > > >
    > > > All new articles provide code in C# and VB.NET.
    > > > Subscribe to the RSS feeds provided and never miss a new article.
    > > >
    > > >
    > > >
    > > >
    > > >
    > > > "Jerad Rose" <no@spam.com> wrote in message
    > > > news:eJEfmYcAFHA.1296@TK2MSFTNGP10.phx.gbl...
    > > > >I have a seemingly simple problem that I've been unable to find the
    > > > >solution
    > > > > for.
    > > > >
    > > > > I have 15 sets of predefined palettes, each having 15 colors.  All
    I'm
    > > > > trying to do, is load images (jpg, gif, or bmp) or any size into a
    > 32x32
    > > > > 15-color image.  I know how to resize the image to a 32x32 bitmap,
    but
    > > > > then
    > > > > I want this image to be "fitted" into these 15-color palettes, using
    > the
    > > > > nearest matching color for each pixel from a given palette.
    > > > >
    > > > > I think I know how to build my palette for my bitmap:
    > > > >
    > > > >    Public Function GetPaletteOfIndex(ByVal iPaletteIndex As Integer)
    > As
    > > > > ColorPalette
    > > > >        Dim bmp As Bitmap = New Bitmap(1, 1,
    > > PixelFormat.Format8bppIndexed)
    > > > >        Dim pal As ColorPalette = bmp.Palette
    > > > >
    > > > >        Dim i As Integer
    > > > >        For i = 0 To 14
    > > > >            'clrPalette is a preset 15x15 array of Color objects
    > > > >            pal.Entries(i) = clrPalette(iPaletteIndex, i)
    > > > >        Next
    > > > >
    > > > >        'set the 16th (unused) Entry to transparent
    > > > >        pal.Entries(15) = Color.FromArgb(0)
    > > > >        bmp.Dispose()
    > > > >        Return pal
    > > > >    End Function
    > > > >
    > > > > I'm just not sure where to go from here.  I've tried loading an
    image
    > > into
    > > > > the bitmap predefined w/ this palette, but I think instead of it
    using
    > > the
    > > > > predefined palette, it overwrites it w/ the palette from the file.
    > I've
    > > > > also tried drawing an image into the bitmap w/ the predefined
    palette,
    > > but
    > > > > you can't use Graphics from an 8bpp bitmap.
    > > > >
    > > > > I've read this article:
    > > > > http://support.microsoft.com/?id=319061
    > > > >
    > > > > ... but it looks like it's calculating the "nearest color" on its
    own
    > > (and
    > > > > this example is using a grayscale palette).  Plus, the memory stuff
    > > there
    > > > > (LockBits, Scan0, Stride) kinda loses me -- surely all that isn't
    > > > > necessary
    > > > > for what I'm trying to do.
    > > > >
    > > > > I've searched on the Graphics.GetNearestColor function, which seems
    > like
    > > > > it
    > > > > would be what I need, but I'm unsure what it's getting the nearest
    > color
    > > > > *of*.  It would be perfect if this function was a member of the
    > > > > ColorPalette
    > > > > object, and it would just return the closest match for that color in
    > > that
    > > > > palette, but alas, this function is on the Graphics object (which
    > can't
    > > be
    > > > > obtained on anything other than a 32bpp bitmap).  So I'm not even
    sure
    > > in
    > > > > what case I would use the GetNearestColor function.
    > > > >
    > > > > So, is what I'm trying to do really that difficult to accomplish?  I
    > > would
    > > > > think this would be a fairly common practice, and not that difficult
    > to
    > > > > pull
    > > > > off.
    > > > >
    > > > > Thanks so much in advance for any help.
    > > > >
    > > > > Jerad
    > > > >
    > > > >
    > > >
    > > >
    > >
    > >
    >
    >
    

  • Next message: Daniel: "PrintPreviewDialog doesn't show any margin"

    Relevant Pages

    • Re: Changing colors of a colorpalette doesnt work!
      ... The GDI+ FAQ has an article on transparent GIF images that has code that demonstrates how to modify a colour palette. ... Is it possible to change the colors of a colorpalette from an existing image and then save it to a file with the new colorpalette? ...
      (microsoft.public.dotnet.framework.drawing)
    • Re: Transparent GIF
      ... The code in the example reads the existing palette just fine. ... Answer those GDI+ questions with the GDI+ FAQ ... snap-to-grid and Layered Windows are ...
      (microsoft.public.dotnet.framework.drawing)
    • Re: Working with indexed bitmaps
      ... Internally GDI+ uses a 32bpp format for images. ... quantize a palette and save the final image. ... You may load the images as indexed but use GDI to draw and manipulate the ...
      (microsoft.public.dotnet.framework.drawing)
    • Re: GIF Transparency
      ... for transparency. ... Answer those GDI+ questions with the GDI+ FAQ ... When I save any image as GIF, gdiplus always uses its halftone palette, ...
      (microsoft.public.dotnet.framework.drawing)
    • Re: Gif question
      ... existing GIF file. ... Answer those GDI+ questions with the GDI+ FAQ ... > colors that are in the image's palette are accepted. ...
      (microsoft.public.dotnet.framework.drawing)