Number of colors in an image

Discussion in 'Python' started by Laszlo Zsolt Nagy, Nov 26, 2004.

  1. Hello,

    How can I determine the number of colors used in an image? I tried to
    search on Google but I could figure out. I read the PIL handbook but I
    do not see how to do it. Can anyone help?


    --
    Best regards,
    Laszlo

    mailto:
    web: http://designasign.biz
    Laszlo Zsolt Nagy, Nov 26, 2004
    #1
    1. Advertising

  2. Laszlo Zsolt Nagy

    Will McGugan Guest

    Laszlo Zsolt Nagy wrote:
    > Hello,
    >
    > How can I determine the number of colors used in an image? I tried to
    > search on Google but I could figure out. I read the PIL handbook but I
    > do not see how to do it. Can anyone help?


    You may get a better response on how to do it in Python, but the
    following C++ code should be easy to translate if necessary. All it
    requires is a get pixel function.

    int CImage::CountUsedColours() const
    {
    if ( !IsValid() ) { Error( errImageInvalid ); return 0; }

    const int TableSize= ( 256 * 256 * 256 ) / 8;

    byte CountTable[ TableSize ];
    memset( &CountTable[0], 0, TableSize );

    for( int Y= 0; Y < GetHeight(); Y++ )
    {
    byte* pColour= (byte*)GetLinePointer( Y );
    int WidthCount= GetWidth();

    while( WidthCount-- )
    {
    const CColour colPix= GetPixel( pColour );
    const int Offset= (int)colPix.R << 16 | (int)colPix.G << 8 |
    (int)colPix.B;
    CountTable[ Offset >> 3 ] |= 1 << ( Offset & 7 );
    pColour+= GetBPP();
    }

    }

    int ColourCount= 0;

    for( int n= 0; n < TableSize; n++ )
    {
    const int CountBits= CountTable[n];

    ColourCount+= ( CountBits & 1 );
    ColourCount+= ( CountBits >> 1 ) & 1;
    ColourCount+= ( CountBits >> 2 ) & 1;
    ColourCount+= ( CountBits >> 3 ) & 1;
    ColourCount+= ( CountBits >> 4 ) & 1;
    ColourCount+= ( CountBits >> 5 ) & 1;
    ColourCount+= ( CountBits >> 6 ) & 1;
    ColourCount+= ( CountBits >> 7 );
    }

    OK();
    return ColourCount;
    }


    Regards,

    Will McGugan
    Will McGugan, Nov 26, 2004
    #2
    1. Advertising

  3. Re[2]: Number of colors in an image

    Hello Will,

    Friday, November 26, 2004, 7:48:08 PM, you wrote:

    > Laszlo Zsolt Nagy wrote:
    >> Hello,
    >>
    >> How can I determine the number of colors used in an image? I tried to
    >> search on Google but I could figure out. I read the PIL handbook but I
    >> do not see how to do it. Can anyone help?


    > You may get a better response on how to do it in Python, but the
    > following C++ code should be easy to translate if necessary. All it
    > requires is a get pixel function.


    > int CImage::CountUsedColours() const

    .....

    > Regards,


    > Will McGugan


    Yes, this can be efficient in C++. I'm not sure but possible it is not
    so efficient in Python. Also it would be far better to have direct
    access to the pixels (and not using a method/function). Now I'm
    thinking about ImageMagick and something like this:

    f = os.popen('identify -verbose ' + fullpath + ' | grep -e "Colors:"')
    s = f.read()
    index = s.find(':')
    color_count = long( (s[index+1:]).strip() )

    Probably ImageMagick uses direct access to pixels but it still take
    seconds to run. It is not that portable but I'll stay at this version.

    :)

    Thank you very much.

    --
    Best regards,
    Laszlo

    mailto:
    web:http://designasign.biz
    Laszlo Zsolt Nagy, Nov 26, 2004
    #3
  4. Laszlo Zsolt Nagy

    David Bolen Guest

    Laszlo Zsolt Nagy <> writes:

    > How can I determine the number of colors used in an image? I tried to
    > search on Google but I could figure out. I read the PIL handbook but I
    > do not see how to do it. Can anyone help?


    I saw your later post about using an external ImageMagick, but just in
    case you do want to try it with PIL, one approach is to get the raw
    data from PIL for each band, combining them into a tuple for the color
    code, and then constructing a dictionary to count the colors.

    For example, for an RGB image:

    import sys
    from PIL import Image
    from itertools import izip, repeat

    if __name__ == "__main__":

    im = Image.open(sys.argv[1])
    r = im.getdata(0)
    g = im.getdata(1)
    b = im.getdata(2)

    # Use a dictionary to count colors by constructing it with an
    # iterator of tuples of (pixel,1). The inner izip makes each
    # pixel tuple out of the individual band values, and the outer
    # izip combines it with the infinitely repeating 1 to generate
    # the values for the dictionary constructor.
    colors = dict(izip(izip(r,g,b), repeat(1)))

    print 'Number of colors =', len(colors)

    For a greyscale, or single banded image, it should be faster just to
    use the built-in PIL "histogram" method and take the length of the
    resulting list. You could also generalize the above to handle CMYK
    too by using getbands() to dynamically work with as many bands as
    available.

    The use of the itertools functions helps to keep memory usage down
    (but does require Python 2.3+) in terms of intermediate object
    creation, but it'll still be fairly wasteful since the getband()
    methods return a full list of integer values for the image pixels, and
    the dictionary will have to have a tuple and value for each unique
    color entry.

    On my older PIII-450 desktop with Windows, this processes a 1416x1028
    RGB image with 269750 colors in under 12 seconds. (A 3.2GHz P4
    running FreeBSD does the same image in about 2s). It appears to be
    about 5-6 times faster than a simple nested for loop processing each
    pixel (via PILs getpixel()). Of course, it's nowhere near nowhere
    near what some good C/C++ code could do if it had direct access to the
    image data.

    -- David
    David Bolen, Nov 26, 2004
    #4
  5. On 26 Nov 2004 17:18:04 -0500, rumours say that David Bolen
    <> might have written:

    > # Use a dictionary to count colors by constructing it with an
    > # iterator of tuples of (pixel,1). The inner izip makes each
    > # pixel tuple out of the individual band values, and the outer
    > # izip combines it with the infinitely repeating 1 to generate
    > # the values for the dictionary constructor.
    > colors = dict(izip(izip(r,g,b), repeat(1)))
    >
    > print 'Number of colors =', len(colors)


    A set seems more appropriate in this case:

    color_count = len(set(izip(r, g, b))) # untested code

    >For a greyscale, or single banded image, it should be faster just to
    >use the built-in PIL "histogram" method and take the length of the
    >resulting list.


    More like the count of non-zero elements in the histogram; I believe the
    length of the resulting list will be constant (ie 256).
    --
    TZOTZIOY, I speak England very best,
    "Tssss!" --Brad Pitt as Achilles in unprecedented Ancient Greek
    Christos TZOTZIOY Georgiou, Nov 26, 2004
    #5
  6. Re[2]: Number of colors in an image

    Hello David,

    Friday, November 26, 2004, 11:18:04 PM, you wrote:


    > For example, for an RGB image:


    > import sys
    > from PIL import Image
    > from itertools import izip, repeat


    > if __name__ == "__main__":


    > im = Image.open(sys.argv[1])
    > r = im.getdata(0)
    > g = im.getdata(1)
    > b = im.getdata(2)
    > print 'Number of colors =', len(colors)


    Thank you, this was very helpful. I'll try to use this one instead of
    ImageMagick. (The identify program does not work in some cases...)

    --
    Best regards,
    Laszlo

    mailto:
    web:http://designasign.biz
    Laszlo Zsolt Nagy, Nov 26, 2004
    #6
  7. Laszlo Zsolt Nagy

    Tim Hoffman Guest

    Have a look at the histogram function of PIL


    Tim
    Laszlo Zsolt Nagy wrote:
    > Hello David,
    >
    > Friday, November 26, 2004, 11:18:04 PM, you wrote:
    >
    >
    >
    >>For example, for an RGB image:

    >
    >
    >> import sys
    >> from PIL import Image
    >> from itertools import izip, repeat

    >
    >
    >> if __name__ == "__main__":

    >
    >
    >> im = Image.open(sys.argv[1])
    >> r = im.getdata(0)
    >> g = im.getdata(1)
    >> b = im.getdata(2)
    >> print 'Number of colors =', len(colors)

    >
    >
    > Thank you, this was very helpful. I'll try to use this one instead of
    > ImageMagick. (The identify program does not work in some cases...)
    >
    Tim Hoffman, Nov 27, 2004
    #7
  8. Laszlo Zsolt Nagy

    David Bolen Guest

    Christos "TZOTZIOY" Georgiou <> writes:

    > A set seems more appropriate in this case:
    >
    > color_count = len(set(izip(r, g, b))) # untested code


    Well, while potentially premature optimization, I was trying for
    performance in this case. In Python 2.3, the sets module is coded in
    Python, and just wraps a dictionary, and when handed an iterable, ends
    up looping (in Python) with individual dictionary key assignments.
    Although I didn't specifically test sets, when I did a loop like that
    myself, it was 5-6 times slower than directly building the dictionary.

    That might change in 2.4 with the built-in set - it's still a wrapper
    around dict but knows it's just directly setting items to a true value
    so can avoid dealing with the tuples that dict does (not to mention I
    don't have to build the extra tuple).

    Although I expect the direct support in PIL 1.1.5 that Fredrik posted
    about will be best.

    > >For a greyscale, or single banded image, it should be faster just to
    > >use the built-in PIL "histogram" method and take the length of the
    > >resulting list.

    >
    > More like the count of non-zero elements in the histogram; I believe the
    > length of the resulting list will be constant (ie 256).


    Oops, definitely yes.

    -- David
    David Bolen, Nov 30, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?RGVuaXNl?=

    Dropdownlist border and image colors

    =?Utf-8?B?RGVuaXNl?=, Jul 25, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    10,601
    =?Utf-8?B?RGVuaXNl?=
    Jul 26, 2005
  2. Oliver Albrecht

    Image.putpalette(Colors)?

    Oliver Albrecht, May 17, 2005, in forum: Python
    Replies:
    4
    Views:
    557
    Oliver Albrecht
    May 18, 2005
  3. Todd
    Replies:
    2
    Views:
    622
    Andrew Thompson
    Sep 26, 2007
  4. AAaron123

    TreeNode colors come from anchor colors

    AAaron123, Aug 7, 2008, in forum: ASP .Net
    Replies:
    1
    Views:
    536
    darrel
    Aug 7, 2008
  5. ZelluX
    Replies:
    3
    Views:
    1,882
    Peter Otten
    Dec 1, 2008
Loading...

Share This Page