The easiest way is to use the `numpy` interface for this, since it allows you to do operations on the whole image:

    from PIL import Image
    import numpy as np
    
    def _colour_mask(img, colour):
        """Finds all indices of a single colour in a PIL.Image"""
        if len(img.shape) == 3:
            return (img == colour).all(axis=2).nonzero()
        elif len(image.shape) == 2:
            return (img == colour).nonzero()
        else:
            raise ValueError("Invalid image shape {}".format(img.shape))


    def _convert_colour(img, incolour, outcolour):
        """Replaces incolour with outcolour in a PIL.Image.
        
        Returns a new PIL.Image.
        Assumes that img has as many channels as len(incolour) and len(outcolour).
        """ 
        img = np.array(img)
        img[_colour_mask(img, incolour)] = outcolour
        return Image.fromarray(img)


    def convert_colour(region_number, incolour, outcolour):
        file_name = region_list.regions_d[region_number][0]
        img = Image.open(file_name)
        new_img = _convert_colour(img, incolour, outcolour)
        new_img.save(file_name, "PNG")
        colour_change_single(region_number, outcolour)