class ReflectiveRetrieval: def __init__(self, xy, image): self.image_mapper = ImageMapper() self.image = self.image_mapper.read_file(image).resize(xy) def get(self, pixel): return self.image_mapper.read_image( self.image_mapper.colorize_image(self.image, pixel) )
class LibraryRetrieval: def __init__(self, xy): self.image_mapper = ImageMapper() self.xy = xy self.weight = .9 # decrease for fine tuning color spectrum values def load_library(self, library): if not isinstance(library, ImageLibrary): raise ValueError("library must be an ImageLibrary") self.image_library = library self.image_library.init() def get(self, pixel): if not hasattr(self, 'image_library'): raise ValueError("no image library has been loaded") # retrieve image file = self.image_library.next(pixel) image = self.image_mapper.read_file(file).resize(self.xy) # mask to specific color tone image = self.image_mapper.colorize_image(image, pixel, self.weight) return self.image_mapper.read_image(image)
from image_library import ImageRetrievalFactory, ImageLibrary import os import shutil from image import ImageMapper test_library = 'test_image_library' image_mapper = ImageMapper() def test_init_fails_with_no_library(): test_subject = ImageLibrary(test_library) remove_library() try: test_subject.init() raise RuntimeError("expected ImageLibraryError") except ImageLibrary.ImageLibraryError: pass def test_init_fails_with_empty_library(): test_subject = ImageLibrary(test_library) create_library() try: test_subject.init() raise RuntimeError("expected ImageLibraryError") except ImageLibrary.ImageLibraryError: pass remove_library() def test_init_fails_with_empty_subfolders():
from image import ImageMapper from PIL import Image import collections testSubject = ImageMapper() def test_read_file(): result = testSubject.read_file('test/data/nature.jpg') assert isinstance(result, Image.Image) def test_read_pixels(): result = testSubject.read_pixels('test/data/nature.jpg') assert isinstance(result, collections.Sequence) # image map assert isinstance(result[0], collections.Sequence) # col map assert isinstance(result[0][0], collections.Sequence) # pixel def test_read_image_equates_to_read_pixels(): result = testSubject.read_image(testSubject.read_file('test/data/nature.jpg')) assert isinstance(result, collections.Sequence) # image map assert isinstance(result[0], collections.Sequence) # col map assert isinstance(result[0][0], collections.Sequence) # pixel def test_write_pixels(): file = 'test/data/out/image-mapper.jpg' colors = [(255,0,0),(0,255,0),(0,0,255)] colorsX = 30 y = 100 pixels = [] for c in colors: for i in range(0, colorsX): col = []
def __init__(self, library_name=LIBRARY_NAME): self.library_path = os.path.dirname(os.path.realpath(__file__)) \ + '/' + library_name self.color_mapper = ImageLibrary.ColorMapper() self.image_mapper = ImageMapper()
class ImageLibrary: LIBRARY_NAME = 'image_library' def __init__(self, library_name=LIBRARY_NAME): self.library_path = os.path.dirname(os.path.realpath(__file__)) \ + '/' + library_name self.color_mapper = ImageLibrary.ColorMapper() self.image_mapper = ImageMapper() def init(self): self.library_files = {} try: library_dirs = os.listdir(self.library_path) except FileNotFoundError: raise self.ImageLibraryError("No image library found at {0}" .format(self.library_path)) for color in self.ColorMapper.COLOR_SPECTRUM: if not color in library_dirs: raise self.ImageLibraryError( "Local image library is missing directory for color {0}" .format(color)) images = os.listdir(self.library_path + '/' + color) if not len(images) > 0: raise self.ImageLibraryError( "Local image library has no images under directory {0}" .format(color)) self.library_files[color] = [0, images] def create(self): if not os.path.isdir(self.library_path): os.mkdir(self.library_path) for color in self.ColorMapper.COLOR_SPECTRUM: color_dir = self.library_path + '/' + color if not os.path.isdir(color_dir): os.mkdir(color_dir) def next(self, pixel): if not hasattr(self, 'library_files'): raise self.ImageLibraryError("This object has not been initialized") color = self.color_mapper.name(pixel) color_list = self.library_files[color] index = color_list[0] # we have reached the end of the image files for this color if index >= len(color_list[1]): index = 0 # increment for next retrieval self.library_files[color][0] = index + 1 return "{0}/{1}/{2}".format( self.library_path, color, self.library_files[color][1][index] ) def add_file(self, color, file, size): destination_file = os.path.basename(file) if os.path.exists("{0}/{1}/{2}" .format(self.library_path, color, destination_file)): destination_file = "{0}_{1}".format(time.time(), destination_file) # add scaled file image = self.image_mapper.read_file(file) image.thumbnail((size, size)) image.save("{0}/{1}/{2}" .format(self.library_path, color, destination_file)) # remove original os.remove(file) ## for reporting out library state issues class ImageLibraryError(Exception): def __init__(self, message): self.message = message def __str__(self): return repr(self.message) ## maps from pixels to library colors class ColorMapper: # RBG color wheel averages tuned from https://rgbcolorcode.com/ COLOR_SPECTRUM = { 'blue': PixelFactory.parse((57, 85, 224)), 'brown': PixelFactory.parse((152, 118, 84)), 'gray': PixelFactory.parse((128, 128, 128)), 'green': PixelFactory.parse((27, 158, 0)), 'lilac': PixelFactory.parse((182, 60, 201)), 'orange': PixelFactory.parse((237, 122, 46)), 'pink': PixelFactory.parse((217, 65, 176)), 'red': PixelFactory.parse((180, 0, 0)), 'turquoise': PixelFactory.parse((59, 207, 205)), 'white': PixelFactory.parse((235, 236, 237)), 'yellow': PixelFactory.parse((255, 213, 0)) } def name(self, pixel): closest_distance = PixelFactory.MAX_PIXEL_DISTANCE result = 'white' pixel_object = PixelFactory.parse(pixel) for name, color in self.COLOR_SPECTRUM.items(): color_distance = pixel_object.distance(color) if color_distance < closest_distance: closest_distance = color_distance result = name return result # provide public visibility without knowledge of internals COLORS = ColorMapper.COLOR_SPECTRUM.keys()
def __init__(self, xy): self.image_mapper = ImageMapper() self.xy = xy self.weight = .9 # decrease for fine tuning color spectrum values
def __init__(self, xy, image): self.image_mapper = ImageMapper() self.image = self.image_mapper.read_file(image).resize(xy)
help='Mosaic thumbnail tile X dimension') arg_parser.add_argument('-y', dest='y', type=int, help='Mosaic thumbnail tile Y dimension') arg_parser.add_argument('-o', dest='output_file', type=str, required=True, help='Mosaic output image name') args = arg_parser.parse_args() # mosaic creation constructs dimensions = (args.x or args.thumb_size, args.y or args.thumb_size) image_mapper = ImageMapper() mosaic_builder = Mosaic() pixel_analyzer = PixelAnalyzer() image_retriever = ImageRetrievalFactory.construct(args.source_type, dimensions, args.input_file) image_library = ImageLibrary() print("Parsing source image...") mosaic = mosaic_builder.tile(image_mapper.read_pixels(args.input_file), dimensions) if args.source_type == ImageRetrievalFactory.RETRIEVE_LIBRARY: print("Loading image library...") image_retriever.load_library(image_library) print("Generating photomosaic...")