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)