def test_bottom_hole_B1(self): """ ---------------------- | | | | |------|-------------| | | | |--------------------- | | --------------- """ page = Page(30, 3) self.force_cell_position(0) self.prevent_cell_extension() page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) self.force_cell_extension() page.add_cell(Photo("img", 10, 5)) page.add_cell(Photo("img", 10, 5)) wanted = ("[10 10] [10 10] [10 10]\n" "[10 10] [20 10-- ------]\n" "[20 10-- ------] ") self.assertEqual(repr(page), wanted) page.remove_bottom_holes() wanted = ("[10 10] [10 10] [10 10]\n" "[10 10] [20 10-- ------]\n" " [20 10-- ------]") self.assertEqual(repr(page), wanted)
class UserCollage(object): """Represents a user-defined collage A UserCollage contains a list of photos (referenced by filenames) and a collage.Page object describing their layout in a final poster. """ def __init__(self, photolist): self.photolist = photolist def make_page(self, opts): # Define the output image height / width ratio ratio = 1.0 * opts.out_h / opts.out_w # Compute a good number of columns. It depends on the ratio, the number # of images and the average ratio of these images. According to my # calculations, the number of column should be inversely proportional # to the square root of the output image ratio, and proportional to the # square root of the average input images ratio. avg_ratio = (sum(1.0 * photo.h / photo.w for photo in self.photolist) / len(self.photolist)) # Virtual number of images: since ~ 1 image over 3 is in a multi-cell # (i.e. takes two columns), it takes the space of 4 images. # So it's equivalent to 1/3 * 4 + 2/3 = 2 times the number of images. virtual_no_imgs = 2 * len(self.photolist) no_cols = int(round(math.sqrt(avg_ratio / ratio * virtual_no_imgs))) self.page = Page(opts.out_w, ratio, no_cols) for photo in self.photolist: self.page.add_cell(photo) self.page.adjust()
def test_remove_empty_cols(self): page = Page(1, 100) self.prevent_cell_extension() page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.remove_empty_cols() self.assertEqual(len(page.cols), 5)
def test_bottom_hole_B1(self): """ ---------------------- | | | | |------|-------------| | | | |--------------------- | | --------------- """ page = Page(30, 0.6, 3) self.force_cell_position(0) self.prevent_cell_extension() page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) self.force_cell_extension() page.add_cell(Photo("img", 10, 5)) page.add_cell(Photo("img", 10, 5)) wanted = ("[10 10] [10 10] [10 10]\n" "[10 10] [20 10-- ------]\n" "[20 10-- ------] ") self.assertEqual(repr(page), wanted) page.remove_bottom_holes() wanted = ("[10 10] [10 10] [10 10]\n" "[10 10] [20 10-- ------]\n" " [20 10-- ------]") self.assertEqual(repr(page), wanted)
def test_remove_empty_cols(self): page = Page(1, 0.6, 100) self.prevent_cell_extension() page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.remove_empty_cols() self.assertEqual(len(page.cols), 5)
def make_page(self, opts): # Define the output image height / width ratio ratio = 1.0 * opts.out_h / opts.out_w # Compute a good number of columns. It depends on the ratio, the number # of images and the average ratio of these images. According to my # calculations, the number of column should be inversely proportional # to the square root of the output image ratio, and proportional to the # square root of the average input images ratio. avg_ratio = (sum(1.0 * photo.h / photo.w for photo in self.photolist) / len(self.photolist)) # Virtual number of images: since ~ 1 image over 3 is in a multi-cell # (i.e. takes two columns), it takes the space of 4 images. # So it's equivalent to 1/3 * 4 + 2/3 = 2 times the number of images. virtual_no_imgs = 2 * len(self.photolist) no_cols = int(round(math.sqrt(avg_ratio / ratio * virtual_no_imgs))) self.page = Page(opts.out_w, ratio, no_cols) for photo in self.photolist: self.page.add_cell(photo) self.page.adjust()
def run(args): tmp_file = [] tmp_file_photo = [] if args.user: if args.mode == "owned": url = owned_url elif args.mode == "ordered": url = ordered_url p = requests.get(url.format(args.user)).content url_re = re.compile(r'\<a href="\/item\/(\d+)"') fig_ids = re.findall(url_re, p) for i in fig_ids: u = img_url.format(i) q = requests.get(u).content print("Downloading " + u) if not q or len(q) < 300: u = img_url_big.format(i) print("Retrying " + u) q = requests.get(u).content fp = tempfile.NamedTemporaryFile() fp.write(q) fp.flush() tmp_file.append(fp) elif args.input: for r, d, f in os.walk(args.input): for file in f: tmp_file.append(open(os.path.join(r, file), 'rb')) if args.randomize: random.shuffle(tmp_file) total_x = total_y = 0 harmonic_mean_sum = 0 for i in tmp_file: with Image.open(i.name) as img: total_x += img.size[0] total_y += img.size[1] ratio = (1 / (float(total_y) / total_x)) harmonic_mean_sum += ratio harmonic_mean = len(tmp_file) / harmonic_mean_sum print(harmonic_mean) if not args.collage or args.collage == 1: tmp_file_names = map(lambda x: x.name, tmp_file) res = make_collage(tmp_file_names, args.output, int(300 * math.sqrt(len(tmp_file))), \ harmonic_mean * 300, enlarge=False) elif args.collage == 2: tmp_file_photo = build_photolist(tmp_file) pa = Page(min(4800, total_y / 2), harmonic_mean * 3, int(math.sqrt(len(tmp_file)) * 2)) for t in tmp_file_photo: pa.add_cell(t) pa.adjust() t = RenderingTask(pa, output_file=args.output, quality=QUALITY_BEST) t.start() print("Done")
def test_next_free_col(self): self.force_cell_position(0) self.prevent_cell_extension() page = Page(100, 4) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) wanted = "[25 25] [25 25] " self.assertEqual(repr(page), wanted) page = Page(40, 4) page.add_cell(Photo("img", 10, 20)) page.add_cell(Photo("img", 10, 15)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 22)) wanted = ("[10 20] [10 15] [10 10] [10 10]\n" " [10 22] [10 10] [10 10]") self.assertEqual(repr(page), wanted) page = Page(50, 5) self.force_cell_extension() page.add_cell(Photo("img", 10, 15)) page.add_cell(Photo("img", 10, 10)) self.prevent_cell_extension() page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 50)) wanted = ("[20 30-- ------] [20 20-- ------] [10 10]\n" " [10 50]") self.assertEqual(repr(page), wanted)
def test_next_free_col(self): self.force_cell_position(0) self.prevent_cell_extension() page = Page(100, 0.6, 4) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) wanted = "[25 25] [25 25] " self.assertEqual(repr(page), wanted) page = Page(40, 0.6, 4) page.add_cell(Photo("img", 10, 20)) page.add_cell(Photo("img", 10, 15)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 22)) wanted = ("[10 20] [10 15] [10 10] [10 10]\n" " [10 22] [10 10] [10 10]") self.assertEqual(repr(page), wanted) page = Page(50, 0.6, 5) self.force_cell_extension() page.add_cell(Photo("img", 10, 15)) page.add_cell(Photo("img", 10, 10)) self.prevent_cell_extension() page.add_cell(Photo("img", 10, 10)) page.add_cell(Photo("img", 10, 50)) wanted = ("[20 30-- ------] [20 20-- ------] [10 10]\n" " [10 50]") self.assertEqual(repr(page), wanted)
def make_collage(output_filename, photos): # Define the output image height / width ratio ratio = 1.0 * out_h / out_w """ Compute a good number of columns. It depends on the ratio, the number of images and the average ratio of these images. According to my calculations, the number of column should be inversely proportional to the square root of the output image ratio, and proportional to the square root of the average input images ratio. """ avg_ratio = sum( 1.0 * photo_from_list.h / photo_from_list.w for photo_from_list in photos) / len(photos) """ Virtual number of images: since ~ 1 image over 3 is in a multi-cell (i.e. takes two columns), it takes the space of 4 images. So it's equivalent to 1/3 * 4 + 2/3 = 2 times the number of images. """ virtual_no_images = 2 * len(photos) no_cols = int(round(math.sqrt(avg_ratio / ratio * virtual_no_images))) border_w = 0.01 border_c = (0, 0, 0) # black # border_c = render.random_color() page = Page(1.0, ratio, no_cols) random.shuffle(photos) for photo_from_list in photos: page.add_cell(photo_from_list) page.adjust() # If the desired ratio changed in the meantime (e.g. from landscape to # portrait), it needs to be re-updated page.target_ratio = 1.0 * out_h / out_w page.adjust_cols_heights() page.scale_to_fit(out_w, out_h) enlargement = float(out_w) / page.w page.scale(enlargement) t = render.RenderingTask( page, output_file=output_filename, border_width=border_w * max(page.w, page.h), border_color=border_c) t.start()