[Image-SIG] Replacing a single color

Jeff Kunce jeff@corrt.com
Wed, 11 Dec 2002 20:50:47 -0600


--=====================_132905595==_
Content-Type: text/plain; charset="us-ascii"; format=flowed


>I would like to take some images (from ImageGrab) and replace all
>the pixels of one color (the gray plot backgrounds) with another color 
>(white).

Here is some code that will do that (and a demo image to try it on.)

   --Jeff

--=====================_132905595==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="ddpilext.py"

#!/usr/bin/env python
'''\
Some extensions to the PIL library
$Id: ddpilext.py,v 1.1 2002/12/12 02:49:26 jeff Exp $


rgbColorFinder()    returns a mask showing the location of a specified
                    range of colors in a given image


rgbColorReplacer()  returns an image where all pixels in a given range of colors
                    are replaced with a given color


***************************************************************** 
***                                                           *** 
***    That portion of the software in this file written by   *** 
***   Jeffrey J. Kunce is hereby placed in the public domain. *** 
***          - Jeffrey J. Kunce, 2002.                        *** 
***                                                           *** 
***               !!! USE AT YOUR OWN RISK !!!                *** 
***             !!! NO WARRANTIES WHATSOEVER !!!              *** 
***                                                           *** 
***                 email: software@corrt.com                 *** 
***                                                           *** 
***************************************************************** 


'''


import Image, ImageChops


def rgbColorFinder(rgbImg, colormin=(0,0,0), colormax=(255,255,255), allbands=1, rmode='1'):
    '''analyzes an RGB image, returns an image of the same size where each pixel is
            WHITE if the pixel in rgbImage MATCHES the color range colormin-to-colormax, or 
            BLACK if the pixel in rgbImage DOES NOT MATCH the color range.
        a pixel is MATCHES the color range
            if allbands!=0 and if for EVERY color pixel[i],
                colormin[i]<=pixel[i] and pixel[i]<=colormax[i], or
            if allbands==0 and if for ANY color pixel[i],
                colormin[i]<=pixel[i] and pixel[i]<=colormax[i].
        rmode determines the mode of the returned image ("1", "L" or "RGB")
    jjk  12/11/02'''
    inbands = rgbImg.split()
    outbands = []
    for srcband, cmin, cmax in zip(inbands, colormin, colormax):
        outbands.append(srcband.point(lambda v1, v2=cmin, v3=cmax: v2<=v1 and v1<=v3 and 255))
    if allbands==0:
        tband = ImageChops.lighter(ImageChops.lighter(outbands[0], outbands[1]), outbands[2])
    else:
        tband = ImageChops.darker(ImageChops.darker(outbands[0], outbands[1]), outbands[2])
    if rmode=='L':
        return tband
    elif rmode=='RGB':
        return Image.merge('RGB', (tband, tband, tband)) # 'RGB'
    else:  # rmode=='1'
        return tband.convert('1')


def rgbColorReplacer(rgbImg, colormin=(0,0,0), colormax=(32,32,32), colornew=(255,255,255), allbands=1):
    '''analyzes an RGB image,
    finds all colors in the range colormin-to-colormax (see colorFinder()),
    creates and returns, with all found colors replaced by colornew
    jjk  12/11/02'''
    colorMask = rgbColorFinder(rgbImg, colormin, colormax, allbands=allbands)
    rplImg = Image.new(rgbImg.mode, rgbImg.size, colornew)
    return Image.composite(rplImg, rgbImg, colorMask)


def demo01(srcfile='demo_ddpilext_src01.jpg', colormin=(120,15,25), colormax=(215,35,60), colornew=(155, 255, 155)):
    '''just a demo of rgbColorReplacer. Insert your own values.
    jjk  12/11/02'''
    print
    print 'ddpilext.py demo01'
    dstfile1 = 'demo_ddpilext_rgbColorFinder.png'
    dstfile2 = 'demo_ddpilext_rgbColorReplacer.jpg'
    print '...opening file', srcfile
    im1 = Image.open(srcfile)
    print '...finding specified colors:', dstfile1
    im2 = rgbColorFinder(im1, colormin, colormax, colornew)
    im2.save(dstfile1)
    print '...replacing specified colors:', dstfile2
    im3 = rgbColorReplacer(im1, colormin, colormax, colornew)
    im3.save(dstfile2)
    print '...Done'


if __name__=='__main__':
    import pdb
    demo01()

--=====================_132905595==_
Content-Type: image/jpeg; name="demo_ddpilext_src01.jpg";
 x-mac-type="4A504547"; x-mac-creator="4A565752"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="demo_ddpilext_src01.jpg"

/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcU
FhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgo
KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAD6ASYDASIA
AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA
AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3
ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWm
p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEA
AwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSEx
BhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElK
U1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3
uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5t1jU
78ategXt0AJ3AAlb+8feqf8Aamof8/11/wB/m/xo1n/kMX3/AF3k/wDQjVOs4U48q0Lbd9y5/amo
f8/11/3+b/Gl/tTUP+f66/7/ADf41ToNVyR7C5mXBqmof8/11/3+b/GrFvfajKwC3t0Sf+mrf41l
1qaDdrZajb3DIrrG4cowyGwc4NZzgkrpGVWclFuO5cul1mBVL3F98wyP3j81mPqWooxVr27BHYyt
/jXs/wAa/ippHjrQNOs9P0ZLCa3cu8nykn5cbQQBxyfyFeTySwXHhgDZvvYJmDyEciMhNgz9fMrO
Fuqv8jnoYio1eXe3b8/uM7+1NQ/5/rr/AL/N/jR/amof8/11/wB/m/xqnQa6OSPY7OZlz+1NQ/5/
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
2Q==
--=====================_132905595==_
Content-Type: text/plain; charset="us-ascii"; format=flowed


--=====================_132905595==_--