def test_scale(self): # Test the scaling function i = hopper("L").resize((50, 50)) with self.assertRaises(ValueError): ImageOps.scale(i, -1) newimg = ImageOps.scale(i, 1) self.assertEqual(newimg.size, (50, 50)) newimg = ImageOps.scale(i, 2) self.assertEqual(newimg.size, (100, 100)) newimg = ImageOps.scale(i, 0.5) self.assertEqual(newimg.size, (25, 25))
def test_scale(): # Test the scaling function i = hopper("L").resize((50, 50)) with pytest.raises(ValueError): ImageOps.scale(i, -1) newimg = ImageOps.scale(i, 1) assert newimg.size == (50, 50) newimg = ImageOps.scale(i, 2) assert newimg.size == (100, 100) newimg = ImageOps.scale(i, 0.5) assert newimg.size == (25, 25)
def atkinson_dither(image_string): image = base64_to_PIL_image(image_string) image = image.convert('L') pix = image.load() w, h = image.size for y in range(h): for x in range(w): old = pix[x, y] new = 0 if old < 127 else 255 pix[x, y] = new quant_error = old - new if x < w - 1: pix[x + 1, y] += quant_error * 1 // 8 if x < w - 2: pix[x + 2, y] += quant_error * 1 // 8 if x > 0 and y < h - 1: pix[x - 1, y + 1] += quant_error * 1 // 8 if y < h - 1: pix[x, y + 1] += quant_error * 1 // 8 if y < h - 2: pix[x, y + 2] += quant_error * 1 // 8 if x < w - 1 and y < h - 1: pix[x + 1, y + 1] += quant_error * 1 // 8 if w > 1024 or h > 512: image = ImageOps.scale(image, 0.75) return PIL_image_to_base64(image)
def save_scale(): if request.method == "POST": image_src = 'static/uploads/img.png' im = Image.open(image_src) factor = int(request.get_data()) * 2 / 100 im = ImageOps.scale(im, factor) im.save('static/uploads/img.png')
def draw_name_box(name: str, type_: str) -> Image: image = Image.new("RGBA", CARD_SIZE, (255, 0, 0, 0)) # Draw a half-opaque rectangle name_box = ImageDraw.Draw(image) name_box.rectangle( [ NAME_BOX_X, NAME_BOX_Y, NAME_BOX_SIZE_X + NAME_BOX_X, NAME_BOX_SIZE_Y + NAME_BOX_Y, ], fill=COLOUR_CODE, ) # Write the unit name font_size = NAME_BOX_SIZE_Y - (2 * NAME_BOX_MARGIN) logging.info("Font size is %s", font_size) font = ImageFont.truetype( str(ROOT_FOLDER / "SourceSansPro-SemiBold.ttf"), size=font_size, ) name_box.text( (NAME_BOX_X + NAME_BOX_MARGIN, NAME_BOX_Y + NAME_BOX_SIZE_Y / 2), name, font=font, fill=(1, 0, 0), anchor="lm", ) # Add the unit icon icon_file = UNIT_ICON_FOLDER / (type_.lower() + ".png") if not icon_file.exists(): raise RuntimeError("No unit icon found: ", type_) with Image.open(icon_file) as icon_im: icon_im = icon_im.crop(icon_im.getbbox()) scaling_factor = (NAME_BOX_SIZE_Y - 2 * NAME_BOX_MARGIN) / icon_im.height logging.info("Rescale icon %s with factor %s", icon_file, scaling_factor) rescaled_icon = ImageOps.scale(icon_im, scaling_factor) extreme_x = NAME_BOX_X + NAME_BOX_SIZE_X - NAME_BOX_MARGIN extreme_y = NAME_BOX_Y + NAME_BOX_SIZE_Y - NAME_BOX_MARGIN image.paste( rescaled_icon, ( extreme_x - rescaled_icon.width, extreme_y - rescaled_icon.height, extreme_x, extreme_y, ), rescaled_icon, ) return image
def main(): parser = argparse.ArgumentParser() parser.add_argument('--color', '-c', type=int, nargs=3, help="Main color of the sprite", default=(0, 255, 0)) parser.add_argument('--outline', '-o', type=int, nargs=3, help="Color of the sprite's outline") parser.add_argument('--background', '-b', type=int, nargs=3, help="Color of the background", default=(255, 255, 255)) parser.add_argument('--transparency', '-t', action='store_true', help="Use transparent background") parser.add_argument('--size', '-s', type=int, default=10, help="Desired size in pixels for the desired result image") parser.add_argument('--random-color', '-r', action='store_true', help="The main color used will be random, and the outline will be automatically darkened") args = parser.parse_args() outline = args.outline and tuple(args.outline) if args.random_color: # Set random color regardless of what was set in the args args.color = [randint(0, 255) for _ in range(3)] # Generate image img = create_sprite(generate_bitmap(), tuple(args.color), outline, tuple(args.background), args.transparency) # Save image to a file as PNG with a random filename random_filename = ''.join(choice(string.ascii_letters) for _ in range(16)) # Scale the image to the desired size if args.size > 10: img = ImageOps.scale(img, args.size / 10, resample=Image.NONE) img.save(random_filename + '.png')
def atkinson_dither(in_file): img = Image.open(in_file).convert('L') pixel = img.load() w, h = img.size for y in range(h): for x in range(w): oldpixel = pixel[x, y] newpixel = round(oldpixel / 256, 0) pixel[x, y] = newpixel quant_error = oldpixel - newpixel if x < w - 1: pixel[x + 1, y] += quant_error * 1 // 8 if x < w - 2: pixel[x + 2, y] += quant_error * 1 // 8 if x > 0 and y < h - 1: pixel[x - 1, y + 1] += quant_error * 1 // 8 if y < h - 1: pixel[x, y + 1] += quant_error * 1 // 8 if y < h - 2: pixel[x, y + 2] += quant_error * 1 // 8 if x < w - 1 and y < h - 1: pixel[x + 1, y + 1] += quant_error * 1 // 8 if w > 1024 or h > 512: img = ImageOps.scale(img, 0.75) img.save(in_file + "_output.png") return in_file + '_output.png'
def colour_dither(in_file): img = Image.open(in_file).convert('RGB') print('hello') size = img.size if size[0] > 1024 or size[1] > 512: img = ImageOps.scale(img, 0.75) print("size reduced") img_data = list(img.getdata()) length = len(list(img.getdata())) freq_dist = FreqDist(img_data) top_256_colours = freq_dist.most_common(256) palette = [] for colour in top_256_colours: palette.append(colour[0]) while len(palette) < 256: palette.append((0, 0, 0)) try: flat_palette = reduce(lambda a, b: a + b, palette) assert len(flat_palette) == 768 palette_img = Image.new('P', (1, 1), 0) palette_img.putpalette(flat_palette) newimage = img.quantize(palette=palette_img) newimage.save(in_file + '_output.png') return in_file + '_output.png' except Exception as inst: print(type(inst)) print(inst.args) return in_file
def resize_image(self, image): (img_width, img_height) = image.size logging.info("orig {}/{}".format(img_width, img_height)) if not self.upscale and ((img_width <= self.basewidth) and (img_height <= self.baseheight)): ratio = 1 else: ratio = min(self.basewidth / img_width, self.baseheight / img_height) logging.info("ratio: {}".format(ratio)) wsize = int(img_width * ratio) hsize = int(img_height * ratio) logging.info("new size: {}/{}".format(wsize, hsize)) try: resized_image = ImageOps.scale(image, ratio) except: logging.warning("exception in ImageOps.scale: {}".format( sys.exc_info()[0])) image.close() return (resized_image)
def _update_zoom(self, *change): """ Update the cached zoomed image. This operation is time consuming and should be computed as little as possible. """ self.zoomed_image = ImageOps.scale(self.current_image, self.zoom_scale) self._update_crop()
def do_texture(path, id, textures, values, thumb_sizes, args): if not path: return if path not in textures: return pptr = textures[path] texture = pptr.read() flipped = None filename, exists = get_filename(args.outdir, args.orig_dir, id, ext=".png") if not (args.skip_existing and exists): print("-> %r" % (filename)) flipped = ImageOps.scale(texture.image, 1).convert("RGB") flipped.save(filename) for format in args.formats: ext = "." + format filename, exists = get_filename(args.outdir, args.tiles_dir, id, ext=ext) if not (args.skip_existing and exists): tile_texture = generate_tile_image(texture.image, values["tile"]) print("-> %r" % (filename)) tile_texture.save(filename) if ext == ".png": # skip png generation for thumbnails continue for sz in thumb_sizes: thumb_dir = "%ix" % (sz) filename, exists = get_filename(args.outdir, thumb_dir, id, ext=ext) if not (args.skip_existing and exists): if not flipped: flipped = ImageOps.scale(texture.image, 1).convert("RGB") thumb_texture = flipped.resize((sz, sz)) print("-> %r" % (filename)) thumb_texture.save(filename)
def PaintGraphicsArea(self, paintEvent): self.outputView.ResultGraphicsArea.setAutoFillBackground(True) painter = QtGui.QPainter(self.outputView.ResultGraphicsArea) displayImage = ImageOps.invert( self.application.nestingRun.DisplayImage) scaleFactor = min( self.outputView.ResultGraphicsArea.height() / displayImage.height, self.outputView.ResultGraphicsArea.width() / displayImage.width) displayImage = ImageOps.scale(displayImage, scaleFactor) painter.drawImage(0, 0, ImageQt.ImageQt(displayImage))
def rescale(im): # Assume 72 DPI if we don't know, as this is # one of the lowest common DPI values. try: dpi = im.info['dpi'] except KeyError: dpi = 72 target_dpi = 300 factor = target_dpi / dpi return ImageOps.scale(im, factor)
def scalare(): if request.method == "POST": delete_images() image_src = 'static/uploads/img.png' im = Image.open(image_src) # Convertim datele primite care apartin [0,100] in date care apartin [0,2] # Pentru factor = 1 imaginea este cea originala, valori din ce in ce mai mici (<1) imaginea se micsoreaza # si pentru valori din ce in ce mai mari (>1) imaginea se mareste factor = int(request.get_data()) * 2 / 100 im_scale = ImageOps.scale(im, factor) imgname = 'img_scale_' + str(factor) + '.png' im_scale.save('static/uploads/' + imgname) image_url_scale = url_for('static', filename="uploads/" + imgname) return jsonify({'image_url_scale': image_url_scale})
def fit_image(img: Image.Image, size) -> Tuple[Image.Image, Tuple[int, int, int, int]]: img_width, img_height = img.size desired_width, desired_height = size ratio = min(desired_width / img_width, desired_height / img_height) img = ImageOps.scale(img, ratio) width, height = img.size x, y = ((desired_width - width) // 2, (desired_height - height) // 2) border = (x, y, desired_width - x - width, desired_height - y - height) img = ImageOps.expand(img, border=border, fill="white") return img, (x, y, width, height)
def reload_image_label(self, image, label): if image.size[0] > _img_size[0] or image.size[1] > _img_size[1]: img = ImageOps.scale( image, min((expected / actual for expected, actual in zip(_img_size, image.size)))) else: img = image if img.mode != "RGB": img = img_utils.add_transparency_grid(img) img_tk = ImageTk.PhotoImage(img) label.configure(image=img_tk) label.image = img_tk
def generate_pixel_image(image_string): ''' https://stackoverflow.com/questions/30520666/pixelate-image-with-pillow ''' block_size = 16 size = (block_size, block_size) image = base64_to_PIL_image(image_string) im = image.convert('RGB') img_data = list(im.getdata()) freq_dist = FreqDist(set(img_data)) most_common = freq_dist.most_common(256) palette = [] for colour in most_common: palette.append(colour[0]) while len(palette) < 256: palette.append((0, 0, 0)) try: flat_palette = reduce(lambda a, b: a + b, palette) assert len(flat_palette) == 768 palette_img = Image.new('P', (1, 1), 0) palette_img.putpalette(flat_palette) multiplier = 8 scaled_img = im.resize((size[0] * multiplier, size[1] * multiplier), Image.ANTIALIAS) reduced_img = scaled_img.quantize(palette=palette_img) rgb_img = reduced_img.convert('RGB') out = Image.new('RGB', size) for x in range(size[0]): for y in range(size[1]): #sample and get average color in the corresponding square histogram = defaultdict(int) for x2 in range(x * multiplier, (x + 1) * multiplier): for y2 in range(y * multiplier, (y + 1) * multiplier): histogram[rgb_img.getpixel((x2, y2))] += 1 color = max(histogram.items(), key=operator.itemgetter(1))[0] out.putpixel((x, y), color) new_file = ImageOps.scale(out, 50) print("pixe_image done") output = PIL_image_to_base64(new_file) #https://docs.python.org/3/tutorial/errors.html except Exception as inst: print(type(inst)) print(inst.args) output = image_string return output
def image_merge(in_file): img = Image.open(in_file).convert('RGB') size = img.size if size[0] > 1024 or size[1] > 512: img = ImageOps.scale(img, 0.75) print("size reduced") r, g, b = img.split() colours = [] colours.extend([r, g, b]) a = choice(colours) b = choice(colours) c = choice(colours) a = ImageChops.offset(a, randint(-20, 20), randint(-10, 10)) #ImageChops.multiply(g, r).save(in_file+'_output.png') Image.merge("RGB", (a, b, c)).save(in_file + '_output.png') print("image_merge done\n") return in_file + '_output.png'
def generate_pixel_image(in_file): block_size = 16 size = (block_size, block_size) im = Image.open(in_file).convert('RGB') img_data = list(im.getdata()) length = len(list(im.getdata())) freq_dist = FreqDist(set(img_data)) top_ten_colours = freq_dist.most_common(256) palette = [] for colour in top_ten_colours: palette.append(colour[0]) while len(palette) < 256: palette.append((0, 0, 0)) try: flat_palette = reduce(lambda a, b: a + b, palette) assert len(flat_palette) == 768 palette_img = Image.new('P', (1, 1), 0) palette_img.putpalette(flat_palette) multiplier = 8 scaled_img = im.resize((size[0] * multiplier, size[1] * multiplier), Image.ANTIALIAS) reduced_img = scaled_img.quantize(palette=palette_img) rgb_img = reduced_img.convert('RGB') out = Image.new('RGB', size) for x in range(size[0]): for y in range(size[1]): #sample and get average color in the corresponding square histogram = defaultdict(int) for x2 in range(x * multiplier, (x + 1) * multiplier): for y2 in range(y * multiplier, (y + 1) * multiplier): histogram[rgb_img.getpixel((x2, y2))] += 1 color = max(histogram.items(), key=operator.itemgetter(1))[0] out.putpixel((x, y), color) new_file = ImageOps.scale(out, 50) out_file, ext = in_file, ext = os.path.splitext(in_file) new_file.save(out_file + "_output.png") print("pixe_image done") return (out_file + "_output.png") #https://docs.python.org/3/tutorial/errors.html except Exception as inst: print(type(inst)) print(inst.args) return (in_file)
def main(filename, mode, tone): if path.isfile(filename): source_im = Image.open(filename) width, hight = source_im.size if mode == "wide": ratio = 5000/width if mode == "high": ratio = 5000/hight im = ImageOps.scale(source_im,ratio*0.8) wi, hi = im.size wi2 = int((5000 - wi)/2) hi2 = int((5000 - hi)/2) if tone == "light": im = ImageOps.expand(im, border = (wi2,hi2), fill="#E5E5E5") if tone == "dark": im = ImageOps.expand(im, border = (wi2,hi2), fill="#0e0e0e") im.save(f'exp_{filename}') else: exit("No source file found!")
async def create_level_image(ctx, name, url, level, rank): colors = { range(0, 10): (155, 155, 155), range(10, 20): (192, 41, 66), range(20, 30): (217, 91, 67), range(30, 40): (254, 204, 35), range(40, 50): (70, 122, 60), range(50, 60): (78, 141, 219), range(60, 70): (118, 82, 201), range(70, 80): (194, 82, 201), range(80, 90): (84, 36, 55), range(90, 100): (153, 124, 82) } for color_range in colors: if level <= 100 and level in color_range: color = colors[color_range] break elif 1000 > level > 100 and level - int( str(level)[0]) * 100 in color_range: color = colors[color_range] break else: color = (155, 155, 155), role = ctx.message.author.roles xp_current_lvl = await self.lvl_xp(level) xp_next_lvl = await self.lvl_xp(level + 1) xp_current = get_xp_from_user(ctx.guild.id, name.id) step = xp_next_lvl - xp_current_lvl state = xp_current - xp_current_lvl try: img = Image.open(r'img/stats/bg{}.png'.format( round(round(state / step * 100) / 2))) except: img = Image.open(r'img/stats/bg0.png') response = requests.get(url) pb = Image.open(BytesIO(response.content)) img = ImageOps.scale(img, factor=2) img = ImageOps.expand(img, border=150, fill="black") pb = pb.resize((456, 430), Image.ANTIALIAS) pb = ImageOps.expand(pb, border=15, fill=f'{max(role).colour}') img.paste(pb, (130, 75)) xp_string = f"XP: {xp_current} / {xp_next_lvl}" # Font Positions level_positions = { 1: (410, 585), 2: (355, 585), 3: (300, 585), 4: (230, 585) } nxt_level_positions = { 1: (1720, 585), 2: (1705, 585), 3: (1700, 585), 4: (1700, 585) } # Draw Name draw = ImageDraw.Draw(img) name_level_size = 130 if len( str(name)) <= 19 else 130 - (len(str(name)) - 19) * 5 draw.text((680, 175), f"Rank: #{rank} Level: {level}", color, font=ImageFont.truetype('fonts/micross.ttf', name_level_size)) draw.text((680, 330), f"{name}", color, font=ImageFont.truetype('fonts/micross.ttf', name_level_size)) # Draw Lvl draw.text(level_positions[len(str(level))], f"{level}", color, font=ImageFont.truetype('fonts/micross.ttf', 130)) draw.text(nxt_level_positions[len(str(level))], f"{level + 1}", color, font=ImageFont.truetype('fonts/micross.ttf', 130)) # Draw XP xp_position = (830 - int((int(len(xp_string) - 12) * 25)), 775) draw.text(xp_position, xp_string, (68, 180, 132), font=ImageFont.truetype('fonts/CORBEL.TTF', 115)) with BytesIO() as output: img.save(output, format="PNG") output.seek(0) await ctx.send( file=discord.File(fp=output, filename="image.png"))
async def _process_commands(self, command: str, path: str): # noqa c901 ar = [x.split(" ") for x in [a.strip(" ") for a in command.split(',')]] im: Image = PIL.Image.open(path) # im.load() im = im.convert("RGBA") print(ar) fmt = "png" for e in ar: for i in range(3): e.append(None) if e[0] == "convert": mode = e[1] if not mode or mode not in "bw,rgb,rgba,luma,web,adaptive": raise commands.ConversionError("Unknown conversion mode", original=None) if mode == "bw": im = im.convert("1") if mode in ["rgb", "rgba"]: im = im.convert(mode.upper()) if mode == "luma": im = im.convert("L") if mode == "web": im = im.convert("P") if mode == "adaptive": im = im.convert( "P", palette=ADAPTIVE, colors=min(int(e[2]), 256) if e[2] else 256) if e[0] == "format": if not e[1] or e[1] not in "png,jpg,gif".split(","): raise commands.ConversionError( f"Invalid output format {e[1]}", original=None) fmt = e[1] if e[0] == "bw": im = im.convert("1").convert("RGBA") if e[0] == "luma": im = im.convert("L").convert("RGBA") if e[0] == "autocontrast": im = im.convert("RGB") im = ImageOps.autocontrast(im, int(e[1]) if e[1] else 0) im = im.convert("RGBA") if e[0] == "rotate": im = im.rotate(int(e[1])) if e[0] == "invert": im = ImageOps.invert(im) if e[0] == "grayscale": im = ImageOps.grayscale(im) if e[0] == "equalize": im = ImageOps.equalize(im) if e[0] == "sepia": im = ImageOps.colorize(ImageOps.grayscale(im), (0, 0, 0), (255, 255, 255), mid=(112, 66, 20)) if e[0] == "colorize": im = ImageOps.colorize(ImageOps.grayscale(im), (0, 0, 0), (255, 255, 255), mid=self._color(e[1])) if e[0] == "posterize": im = ImageOps.posterize(im, int(e[1]) if e[1] else 128) if e[0] == "solarize": im = im.convert("RGB") if len(e) > 1: a = int(e[1]) else: a = 128 im = ImageOps.solarize(im, a) im = im.convert("RGBA") if e[0] == "flip": im = ImageOps.flip(im) if e[0] == "mirror": im = ImageOps.mirror(im) if e[0] == "blur": if len(e) > 1: a = int(e[1]) else: a = 2 im = im.filter(ImageFilter.GaussianBlur(a)) if e[0] == "boxblur": if len(e) > 1: a = int(e[1]) else: a = 2 im = im.filter(ImageFilter.BoxBlur(a)) if e[0] == "sharpen": im = im.filter( ImageFilter.UnsharpMask( int(e[1]) if e[1] else 2, int(e[2]) if e[2] else 150, int(e[3]) if e[3] else 3)) if e[0] == "scale": im = ImageOps.scale(im, float(e[1])) if e[0] == "pscale": im = ImageOps.scale(im, float(e[1]), PIL.Image.NEAREST) if e[0] == "scalexy": im = im.resize((int(im.width * float(e[1])), int(im.height * float(e[2])))) if e[0] == "pscalexy": im = im.resize((int( im.width * float(e[1])), int(im.height * float(e[2]))), PIL.Image.NEAREST) if e[0] == "scaleto": im = im.resize((int(e[1]), int(e[2])), PIL.Image.BICUBIC) if e[0] == "pscaleto": im = im.resize((int(e[1]), int(e[2])), PIL.Image.NEAREST) if e[0] == "potografy": im = im.resize((int(im.width / 20), int(im.height / 4)), PIL.Image.NEAREST) im = im.resize((int(im.width * 20), int(im.height * 4)), PIL.Image.NEAREST) im = ImageOps.posterize(im, 2) im = ImageOps.colorize(ImageOps.grayscale(im), (0, 0, 0), (255, 255, 255), mid=(112, 66, 20)) im = im.rotate(25) if e[0] == "matrix": size = (im.width, im.height) im = im.resize((int(e[1]), int(e[2])), PIL.Image.NEAREST) im = im.resize(size, PIL.Image.NEAREST) a = path.split(".") async with self.lock: self.counter += 1 b = str(self.counter) + "." + fmt # + a[-1] im.save(b) return True, b, os.path.getsize(b)
def get(self, request, pk=None, project_pk=None, image_filename=""): """ Generate a thumbnail on the fly for a particular task's image """ task = self.get_and_check_task(request, pk) image = ImageUpload.objects.filter(task=task, image=assets_directory_path(task.id, task.project.id, image_filename)).first() if image is None: raise exceptions.NotFound() image_path = image.path() if not os.path.isfile(image_path): raise exceptions.NotFound() try: thumb_size = int(self.request.query_params.get('size', 512)) if thumb_size < 1: raise ValueError() quality = int(self.request.query_params.get('quality', 75)) if quality < 0 or quality > 100: raise ValueError() center_x = float(self.request.query_params.get('center_x', '0.5')) center_y = float(self.request.query_params.get('center_y', '0.5')) if center_x < -0.5 or center_x > 1.5 or center_y < -0.5 or center_y > 1.5: raise ValueError() draw_points = self.request.query_params.getlist('draw_point') point_colors = self.request.query_params.getlist('point_color') point_radiuses = self.request.query_params.getlist('point_radius') points = [] i = 0 for p in draw_points: coords = list(map(float, p.split(","))) if len(coords) != 2: raise ValueError() points.append({ 'x': coords[0], 'y': coords[1], 'color': hex2rgb(point_colors[i]) if i < len(point_colors) else (255, 255, 255), 'radius': float(point_radiuses[i]) if i < len(point_radiuses) else 1.0, }) i += 1 zoom = float(self.request.query_params.get('zoom', '1')) if zoom < 0.1 or zoom > 10: raise ValueError() except ValueError: raise exceptions.ValidationError("Invalid query parameters") with Image.open(image_path) as img: if img.mode != 'RGB': img = normalize(img) img = img.convert('RGB') w, h = img.size thumb_size = min(max(w, h), thumb_size) # Move image center if center_x != 0.5 or center_y != 0.5: img = img.crop(( w * (center_x - 0.5), h * (center_y - 0.5), w * (center_x + 0.5), h * (center_y + 0.5) )) # Scale scale_factor = 1 off_x = 0 off_y = 0 if zoom != 1: scale_factor = (2 ** (zoom - 1)) off_x = w / 2.0 - w / scale_factor / 2.0 off_y = h / 2.0 - h / scale_factor / 2.0 win = img.crop((off_x, off_y, off_x + (w / scale_factor), off_y + (h / scale_factor) )) img = ImageOps.scale(win, scale_factor, Image.NEAREST) sw, sh = w * scale_factor, h * scale_factor # Draw points for p in points: d = ImageDraw.Draw(img) r = p['radius'] * max(w, h) / 100.0 sx = (p['x'] + (0.5 - center_x)) * sw sy = (p['y'] + (0.5 - center_y)) * sh x = sx - off_x * scale_factor y = sy - off_y * scale_factor d.ellipse([(x - r, y - r), (x + r, y + r)], outline=p['color'], width=int(max(1.0, math.floor(r / 3.0)))) img.thumbnail((thumb_size, thumb_size)) output = io.BytesIO() img.save(output, format='JPEG', quality=quality) res = HttpResponse(content_type="image/jpeg") res['Content-Disposition'] = 'inline' res.write(output.getvalue()) output.close() return res
def draw_stat_box( move: str, attacks: str, range_: str, hits: str, save: str, ) -> Image: image = Image.new("RGBA", CARD_SIZE, (255, 0, 0, 0)) # Draw a half-opaque rectangle box = ImageDraw.Draw(image) box.rectangle( [ STAT_BOX_X, STAT_BOX_Y, STAT_BOX_SIZE_X + STAT_BOX_X, STAT_BOX_SIZE_Y + STAT_BOX_Y, ], fill=COLOUR_CODE, ) # Draw lines for index in range(1, 5): y_position = (STAT_BOX_Y + STAT_BOX_MARGIN + (2 * index) * ((STAT_BOX_SIZE_Y - 2 * STAT_BOX_MARGIN) / 10)) box.line( ( STAT_BOX_X + STAT_BOX_MARGIN, y_position, STAT_BOX_X + STAT_BOX_SIZE_X - STAT_BOX_MARGIN, y_position, ), fill=(1, 0, 0), ) # Add icons for index, icon in enumerate(["move", "attacks", "range", "hits", "save"]): x_position = int(STAT_BOX_X + (STAT_BOX_SIZE_X / 4)) y_position = int(STAT_BOX_Y + STAT_BOX_MARGIN + (1 + 2 * index) * ((STAT_BOX_SIZE_Y - 2 * STAT_BOX_MARGIN) / 10)) icon_file = STAT_ICON_FOLDER / (icon + ".png") with Image.open(icon_file) as icon_im: icon_im = icon_im.crop(icon_im.getbbox()) scaling_factor = 35 / icon_im.height logging.info("Rescale icon %s with factor %s", icon_file, scaling_factor) rescaled_icon = ImageOps.scale(icon_im, scaling_factor) image.paste( rescaled_icon, ( x_position - rescaled_icon.width // 2, y_position - rescaled_icon.height // 2, ), rescaled_icon, ) # Write the stats font = ImageFont.truetype( str(ROOT_FOLDER / "SourceSansPro-SemiBold.ttf"), size=STAT_BOX_FONT_SIZE, ) for index, stat in enumerate([move, attacks, range_, hits, save]): y_position = (STAT_BOX_Y + STAT_BOX_MARGIN + (1 + 2 * index) * ((STAT_BOX_SIZE_Y - 2 * STAT_BOX_MARGIN) / 10)) box.text( (STAT_BOX_X + (3 * STAT_BOX_SIZE_X / 4), y_position), stat, font=font, fill=(1, 0, 0), anchor="mm", ) return image
def augmentation(self, img, mask, whole_image=False): ow = img.size[0] oh = img.size[1] rh = self.h_size rw = self.w_size if random.random() < 0.5: img = ImageOps.flip(img) mask = ImageOps.flip(mask) if random.random() < 0.5: img = ImageOps.mirror(img) mask = ImageOps.mirror(mask) ''' if random.random() > 0.5: if random.random() < 0.5: zoom = random.uniform(1.0, 1.5) img = ImageOps.scale(img, zoom, Image.BILINEAR) mask = ImageOps.scale(mask, zoom) # x1 = random.randint(0, round(ow * zoom - ow)) # y1 = random.randint(0, round(oh * zoom - oh)) x1 = int(round((ow * zoom - ow) / 2.)) y1 = int(round((oh * zoom - oh) / 2.)) img = img.crop((x1, y1, x1 + ow, y1 + oh)) mask = mask.crop((x1, y1, x1 + ow, y1 + oh)) else: scale = random.uniform(0.5, 1.0) crop_h = int(oh * scale) crop_w = int(ow * scale) # x1 = random.randint(0, round(ow - crop_w)) # y1 = random.randint(0, round(oh - crop_h)) x1 = int(round((ow - crop_w) / 2.)) y1 = int(round((oh - crop_h) / 2.)) img = img.crop((x1, y1, x1 + crop_w, y1 + crop_h)) mask = mask.crop((x1, y1, x1 + crop_w, y1 + crop_h)) ''' if random.random() < 0.5: zoom = random.uniform(1.0, 1.5) img = ImageOps.scale(img, zoom, Image.BILINEAR) mask = ImageOps.scale(mask, zoom) x1 = int(round((ow * zoom - ow) / 2.)) y1 = int(round((oh * zoom - oh) / 2.)) img = img.crop((x1, y1, x1 + ow, y1 + oh)) mask = mask.crop((x1, y1, x1 + ow, y1 + oh)) if random.random() < 0.5: scale = random.uniform(0.5, 1.0) crop_h = int(oh * scale) crop_w = int(ow * scale) x1 = int(round((ow - crop_w) / 2.)) y1 = int(round((oh - crop_h) / 2.)) img = img.crop((x1, y1, x1 + crop_w, y1 + crop_h)) mask = mask.crop((x1, y1, x1 + crop_w, y1 + crop_h)) ''' if random.random() < 0.5: shift_pix = random.randint(-20, 20) img = ImageChops.offset(img, shift_pix) mask = ImageChops.offset(mask, shift_pix) ''' if random.random() < 0.5: angle = random.uniform(-10, 10) img = img.rotate(angle, resample=Image.BILINEAR) mask = mask.rotate(angle) img = img.resize((rw, rh), resample=Image.BILINEAR) mask = mask.resize((rw, rh), resample=Image.NEAREST) return img, mask
images = {} heights_px = [] widths_px = [] for file in glob.glob('*.png'): name = Path(file).stem im = Image.open(file) images[name] = im heights_px.append(im.height) widths_px.append(im.width) #%% padding to max h and w max_w_px = max(widths_px) max_h_px = max(heights_px) for im in images: images[im] = ImageOps.pad(images[im], size=(max_w_px, max_h_px), color='white') #%% calculate image sizes with respect to columns and pagesize page_w_px = int(dpi * page_w_cm // 2.54) page_h_px = int(dpi * page_h_cm // 2.54) max_allowed_w_px = page_w_px // columns scale = max_allowed_w_px / max_w_px for im in images: images[im] = ImageOps.scale(images[im], scale) images[im].save(im + '.png')
def __init__(self, filename, scale=1): self.img = Image.open(filename) self.extract_tags() if scale != 1: self.img = ImageOps.scale(self.img, scale)
from PIL import Image, ImageFilter, ImageOps base = Image.open('assets/test.jpg') # Crop image all sides equal img_crop = ImageOps.crop(base, border=50) img_crop.save('crop_image.jpg') # Crop image with (left,upper,right,lower) pixels img_crop1 = base.crop((0, 380, 600, 510)) img_crop1.save('crop1_image.jpg') # Scale Image img_scale = ImageOps.scale(base, 0.5) img_scale.save('scale_image.jpg') # Convert Image to grey scale img_grey = ImageOps.grayscale(base) img_grey.save('grey_image.jpg') # Invert image img_inv = ImageOps.invert(base) img_inv.save('invert_image.jpg') # Solarize image img_solarize = ImageOps.solarize(base, threshold=100) img_solarize.save('solarize_image.jpg') # Applying BOX BLUR img_blur = base.filter(filter=ImageFilter.BoxBlur(2)) img_blur.save('blur_image.jpg')